#include "client_test_helpers.h"
#include "digest_util.h"
#include "pkcs8.h"
#include "sa_public_key.h"
#include <cstring>
#include <openssl/cmac.h>
#include <openssl/dh.h>
#include <openssl/hmac.h>
#include <openssl/x509.h>
#if OPENSSL_VERSION_NUMBER < 0x30000000
#include <openssl/ecdsa.h>
#include <openssl/rand.h>
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif
#define KEY_ONLY_MASK (~SA_USAGE_BIT_MASK(SA_USAGE_FLAG_UNWRAP) & SA_KEY_USAGE_MASK)
namespace client_test_helpers {
static const uint8_t RSA1024[] = {
0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01,
0x00, 0x02, 0x81, 0x81, 0x00, 0xc4, 0x32, 0x70,
0x15, 0xb3, 0x53, 0xd5, 0xaf, 0x26, 0xc2, 0xcd,
0x6e, 0x87, 0x9f, 0x13, 0x10, 0x9e, 0x3d, 0x8d,
0x6c, 0xb4, 0x1e, 0xc8, 0xbb, 0xf1, 0xbf, 0x7a,
0xc0, 0xce, 0xbf, 0x5c, 0x00, 0x1f, 0x83, 0xd8,
0xe3, 0xf7, 0xe8, 0xa3, 0x79, 0x61, 0xd4, 0x3a,
0xae, 0x49, 0x6d, 0x38, 0x1d, 0x12, 0x74, 0xba,
0x9c, 0xb4, 0x38, 0x61, 0x6b, 0x44, 0x1d, 0xac,
0xf7, 0xa7, 0x7d, 0x8a, 0x80, 0x9f, 0x56, 0x67,
0xb2, 0xe5, 0x45, 0xbc, 0x0d, 0xde, 0xde, 0x63,
0x06, 0x13, 0x4d, 0x06, 0x2e, 0xe2, 0xf9, 0xfa,
0xe4, 0x3b, 0xa6, 0xa0, 0x49, 0xbb, 0x11, 0x23,
0xf8, 0x68, 0x85, 0x3c, 0x1b, 0x92, 0xe1, 0x6c,
0x42, 0x37, 0xe3, 0x1b, 0x7c, 0x7a, 0x25, 0x91,
0x30, 0xd5, 0xa5, 0xf3, 0xbb, 0x91, 0x23, 0xdf,
0x23, 0x94, 0xb8, 0xf2, 0x61, 0x4f, 0xba, 0x73,
0xd1, 0x4b, 0x2b, 0x89, 0x8f, 0x02, 0x03, 0x01,
0x00, 0x01, 0x02, 0x81, 0x81, 0x00, 0x8c, 0x8d,
0xad, 0xaa, 0x7e, 0x2b, 0xe2, 0xfb, 0x75, 0x83,
0x3c, 0xf4, 0xa0, 0x08, 0x1f, 0xfa, 0x59, 0xc2,
0xb2, 0xdc, 0x5b, 0x35, 0x6a, 0x8c, 0xea, 0x25,
0x48, 0xe5, 0x73, 0xb7, 0xb7, 0x4b, 0x07, 0x48,
0xc7, 0x4a, 0x99, 0xc1, 0x79, 0xcb, 0x6d, 0x80,
0x43, 0x01, 0xb4, 0xec, 0x9f, 0xb4, 0x84, 0x12,
0x47, 0xd6, 0x17, 0x6e, 0x04, 0xac, 0x79, 0xc1,
0xe0, 0xb6, 0x12, 0xb1, 0x67, 0x54, 0x77, 0xa2,
0xd4, 0x80, 0xf2, 0x87, 0xb9, 0x56, 0xcc, 0xde,
0xc2, 0x52, 0x09, 0x2d, 0x5b, 0x7b, 0x0e, 0xfa,
0xe2, 0xd8, 0x9e, 0x41, 0xaf, 0xfc, 0x42, 0x0d,
0x24, 0x6c, 0xe2, 0x8b, 0x3a, 0xae, 0x5c, 0x17,
0x11, 0xbb, 0x33, 0x13, 0xb8, 0x66, 0xd6, 0xc6,
0xb1, 0x2f, 0xef, 0xf0, 0x68, 0x0e, 0x2c, 0xf9,
0x41, 0xd2, 0x7f, 0xe0, 0x15, 0xe2, 0x33, 0xf5,
0xd8, 0xb6, 0x01, 0xb0, 0x64, 0x91, 0x02, 0x41,
0x00, 0xf3, 0x37, 0x23, 0xf9, 0xff, 0x24, 0x37,
0x63, 0x10, 0x19, 0x6f, 0x6c, 0x35, 0xa0, 0x41,
0x3c, 0x2c, 0x00, 0xa8, 0x71, 0xa9, 0x09, 0x0e,
0x1f, 0xc7, 0x87, 0x6e, 0x67, 0xf3, 0x8a, 0x76,
0x5f, 0xfb, 0x69, 0x44, 0x22, 0x88, 0x36, 0x1d,
0x31, 0xb9, 0x79, 0xd3, 0x8c, 0x92, 0xb4, 0x0c,
0x0b, 0x72, 0xdd, 0x62, 0x47, 0x86, 0xd7, 0x7d,
0x63, 0xb1, 0xe3, 0x30, 0xb4, 0x8f, 0x89, 0x63,
0x3b, 0x02, 0x41, 0x00, 0xce, 0x82, 0x96, 0xa8,
0x5c, 0x6a, 0x8a, 0x50, 0x31, 0xf1, 0x9c, 0xe3,
0xaa, 0x0d, 0x89, 0xe4, 0xe2, 0x68, 0xe2, 0x25,
0xf7, 0xec, 0x5e, 0xe8, 0xde, 0x68, 0x29, 0x84,
0xf2, 0x58, 0x68, 0xa8, 0xb3, 0x1b, 0x36, 0x68,
0x7c, 0x2d, 0x21, 0xea, 0x92, 0xb5, 0x3a, 0x80,
0xc2, 0x45, 0xbb, 0xc4, 0xfc, 0x38, 0xb0, 0x33,
0xe2, 0xf1, 0x93, 0x83, 0x48, 0x5d, 0x91, 0x31,
0xc4, 0x55, 0x65, 0xbd, 0x02, 0x40, 0x0e, 0x66,
0x2d, 0x53, 0x17, 0xaf, 0xe5, 0x37, 0x90, 0x34,
0x71, 0x4c, 0x4e, 0xc0, 0x76, 0x1c, 0x41, 0xde,
0xa8, 0x1a, 0x52, 0x8f, 0x9e, 0xae, 0x72, 0xf9,
0xa9, 0xa7, 0xad, 0xdb, 0x7c, 0xb6, 0xa2, 0x03,
0xd1, 0x6c, 0xd9, 0xf3, 0x9a, 0x36, 0xdf, 0x6c,
0x3f, 0x02, 0x0b, 0x8d, 0x6d, 0x49, 0x20, 0x3b,
0xcb, 0x1d, 0xc0, 0xf5, 0xf1, 0x0e, 0x7d, 0xf1,
0x9d, 0x68, 0x93, 0x36, 0xe7, 0x11, 0x02, 0x40,
0x4c, 0x12, 0x93, 0x09, 0x26, 0x32, 0x21, 0x0d,
0x75, 0xb8, 0x79, 0x80, 0xec, 0x4d, 0xdc, 0x74,
0x32, 0x6b, 0x4c, 0x93, 0x8c, 0x06, 0xc8, 0xd7,
0xa3, 0xc6, 0x5f, 0x35, 0x18, 0x49, 0x35, 0x14,
0xa0, 0x15, 0xf0, 0x2f, 0x01, 0x3f, 0x66, 0xf5,
0x10, 0x62, 0x2e, 0x50, 0xec, 0x3f, 0xdf, 0xf1,
0xaa, 0xaf, 0xff, 0x48, 0xbd, 0xdb, 0x1b, 0xea,
0x0a, 0xa8, 0x5d, 0x2a, 0x26, 0x17, 0x07, 0x49,
0x02, 0x41, 0x00, 0xb6, 0xc4, 0x4b, 0x68, 0x82,
0xe8, 0x40, 0xc0, 0x70, 0x58, 0xdb, 0x68, 0x49,
0x30, 0x7d, 0x6a, 0xf1, 0xfc, 0x9d, 0x66, 0x33,
0x10, 0x28, 0x1b, 0x54, 0x1d, 0x81, 0xf1, 0x88,
0x9a, 0x6b, 0xb7, 0x1b, 0x7f, 0x36, 0x79, 0xce,
0x02, 0xec, 0x7c, 0x7e, 0x71, 0x37, 0x05, 0x46,
0x33, 0xee, 0x3d, 0x71, 0x8f, 0xb6, 0x16, 0x6c,
0xa6, 0x64, 0xa9, 0xe4, 0x04, 0xc8, 0x12, 0xd7,
0x14, 0xcf, 0xed};
static const uint8_t RSA1024_E3[] = {
0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01,
0x00, 0x02, 0x81, 0x81, 0x00, 0xba, 0xd7, 0x5f,
0xe7, 0x1d, 0x5e, 0x02, 0x09, 0xbc, 0x01, 0xf2,
0x38, 0x56, 0x65, 0x6c, 0x1c, 0x67, 0x0b, 0xc4,
0xef, 0xa3, 0x8e, 0xf1, 0x30, 0xa5, 0x93, 0x55,
0x73, 0x14, 0x18, 0xe0, 0xa7, 0x5b, 0x07, 0xdb,
0x30, 0xca, 0x7e, 0x38, 0x68, 0x84, 0xd4, 0xc0,
0x8b, 0xaf, 0x43, 0x9d, 0x98, 0x5c, 0x1a, 0x0d,
0x0b, 0x16, 0x0d, 0xd1, 0x8c, 0x43, 0xf1, 0xa4,
0x67, 0x9e, 0x78, 0x0c, 0xd1, 0x6b, 0x77, 0x38,
0x2d, 0xfa, 0xb6, 0xd1, 0x02, 0x74, 0xb5, 0xea,
0x2f, 0x65, 0xb8, 0xee, 0xb8, 0xc9, 0xdd, 0x7d,
0x33, 0xb3, 0xaa, 0x4c, 0xe3, 0x14, 0x1c, 0xcd,
0x7f, 0x42, 0xfc, 0xfb, 0x8b, 0xbe, 0xbe, 0x6a,
0x25, 0x9a, 0x52, 0xe5, 0x79, 0x15, 0xec, 0xda,
0x40, 0x42, 0x32, 0xc1, 0x7a, 0xd8, 0x76, 0xb3,
0x0e, 0xff, 0x9c, 0x3f, 0xca, 0x67, 0x40, 0x82,
0xd9, 0x77, 0x52, 0x3b, 0x4f, 0x02, 0x01, 0x03,
0x02, 0x81, 0x80, 0x7c, 0x8f, 0x95, 0x44, 0xbe,
0x3e, 0xac, 0x06, 0x7d, 0x56, 0xa1, 0x7a, 0xe4,
0x43, 0x9d, 0x68, 0x44, 0xb2, 0x83, 0x4a, 0x6d,
0x09, 0xf6, 0x20, 0x6e, 0x62, 0x38, 0xf7, 0x62,
0xbb, 0x40, 0x6f, 0x92, 0x05, 0x3c, 0xcb, 0x31,
0xa9, 0x7a, 0xf0, 0x58, 0x8d, 0xd5, 0xb2, 0x74,
0xd7, 0xbe, 0x65, 0x92, 0xbc, 0x08, 0xb2, 0x0e,
0xb3, 0xe1, 0x08, 0x2d, 0x4b, 0xc2, 0xef, 0xbe,
0xfa, 0xb3, 0x35, 0x22, 0xbd, 0x17, 0x76, 0x2c,
0x43, 0xcd, 0x22, 0x46, 0x47, 0x08, 0x02, 0xf8,
0xdb, 0xf1, 0xe1, 0xfd, 0xb0, 0xe9, 0xfe, 0xa6,
0xbf, 0xe1, 0xc0, 0xe2, 0x37, 0x0d, 0x93, 0x14,
0x1d, 0xec, 0x04, 0xf7, 0x39, 0x50, 0xaf, 0x18,
0xb5, 0xca, 0x0f, 0xef, 0xb3, 0xfe, 0xbd, 0x14,
0x8e, 0xca, 0x50, 0x6e, 0x12, 0x70, 0x6a, 0x93,
0x0a, 0xa7, 0xe6, 0xa6, 0xdd, 0xff, 0x2a, 0x0a,
0xb4, 0xac, 0x2b, 0x02, 0x41, 0x00, 0xf0, 0x5a,
0x71, 0x7b, 0x9c, 0x5b, 0x3a, 0x11, 0x62, 0x65,
0xd9, 0x0f, 0x8a, 0x31, 0x58, 0xae, 0x4d, 0x55,
0x48, 0xc0, 0xb0, 0x55, 0x95, 0x76, 0x7d, 0xeb,
0x8c, 0xd9, 0x99, 0xab, 0x43, 0x7e, 0x84, 0xb2,
0x3f, 0x93, 0xf5, 0x01, 0xed, 0x0e, 0xc3, 0x4f,
0xca, 0x1d, 0x57, 0xd5, 0x22, 0x34, 0x1e, 0x7d,
0xf6, 0x60, 0xd1, 0x58, 0x85, 0x48, 0x1b, 0x54,
0x90, 0xe1, 0x0d, 0xa2, 0xcb, 0xe1, 0x02, 0x41,
0x00, 0xc7, 0x01, 0x23, 0x81, 0x1b, 0xf5, 0xe3,
0x3d, 0xa8, 0xe5, 0x85, 0x1b, 0x66, 0x3d, 0xab,
0x37, 0x7f, 0xfe, 0xd5, 0x75, 0x09, 0x34, 0xe4,
0xcb, 0x42, 0xde, 0xac, 0x49, 0x0b, 0x24, 0xd6,
0x05, 0xc7, 0x36, 0x31, 0x8b, 0x00, 0x40, 0x49,
0x52, 0x6b, 0x0f, 0x12, 0x07, 0x4b, 0x87, 0x6f,
0xce, 0x14, 0xdd, 0x14, 0x0e, 0x51, 0xb3, 0xbe,
0xa8, 0x51, 0x9e, 0xf3, 0x39, 0x59, 0xa0, 0x6d,
0x2f, 0x02, 0x41, 0x00, 0xa0, 0x3c, 0x4b, 0xa7,
0xbd, 0x92, 0x26, 0xb6, 0x41, 0x99, 0x3b, 0x5f,
0xb1, 0x76, 0x3b, 0x1e, 0xde, 0x38, 0xdb, 0x2b,
0x20, 0x39, 0x0e, 0x4e, 0xfe, 0x9d, 0x08, 0x91,
0x11, 0x1c, 0xd7, 0xa9, 0xad, 0xcc, 0x2a, 0x62,
0xa3, 0x56, 0x9e, 0x09, 0xd7, 0x8a, 0x86, 0xbe,
0x3a, 0x8e, 0x16, 0xcd, 0x69, 0xa9, 0x4e, 0xeb,
0x36, 0x3b, 0x03, 0x85, 0x67, 0x8d, 0xb5, 0xeb,
0x5e, 0x6c, 0x87, 0xeb, 0x02, 0x41, 0x00, 0x84,
0xab, 0x6d, 0x00, 0xbd, 0x4e, 0x97, 0x7e, 0x70,
0x99, 0x03, 0x67, 0x99, 0x7e, 0x72, 0x24, 0xff,
0xff, 0x38, 0xf8, 0xb0, 0xcd, 0xed, 0xdc, 0xd7,
0x3f, 0x1d, 0x86, 0x07, 0x6d, 0xe4, 0x03, 0xda,
0x24, 0x21, 0x07, 0x55, 0x80, 0x30, 0xe1, 0x9c,
0xb4, 0xb6, 0xaf, 0x87, 0xaf, 0x9f, 0xde, 0xb8,
0x93, 0x62, 0xb4, 0x36, 0x77, 0xd4, 0x70, 0x36,
0x69, 0xf7, 0x7b, 0x91, 0x15, 0x9e, 0x1f, 0x02,
0x41, 0x00, 0xe6, 0x1e, 0x47, 0x8e, 0x72, 0x60,
0xca, 0x6b, 0x0b, 0x46, 0xe4, 0xdc, 0x1b, 0x2d,
0x79, 0xa5, 0xb9, 0x1a, 0xa4, 0x16, 0xd1, 0x17,
0x53, 0xa8, 0xf2, 0x78, 0x56, 0x65, 0xad, 0x61,
0xec, 0x8c, 0xb4, 0x92, 0xe1, 0x8b, 0x14, 0xb1,
0x9b, 0x20, 0xe5, 0x44, 0xe4, 0xe2, 0x41, 0x3c,
0x5f, 0xfc, 0x54, 0x5f, 0x29, 0x44, 0x59, 0x72,
0xf6, 0x84, 0xc4, 0x66, 0x06, 0x05, 0x19, 0x82,
0x33, 0x89};
static const uint8_t RSA2048[] = {
0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01,
0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf2, 0x6a,
0x52, 0xa0, 0x96, 0xc5, 0xb7, 0x86, 0x6f, 0xc4,
0x35, 0x39, 0x5e, 0x28, 0xd3, 0xa6, 0xab, 0x80,
0x6a, 0xbb, 0x07, 0x10, 0x74, 0xea, 0xe0, 0xfc,
0xef, 0x54, 0xb0, 0x5e, 0x66, 0x34, 0x21, 0x89,
0x35, 0x09, 0xb7, 0x46, 0xf8, 0xb6, 0xf8, 0x86,
0xc0, 0x55, 0xc6, 0xc5, 0x2e, 0x36, 0xcc, 0xb7,
0x24, 0x5e, 0x56, 0xba, 0x2b, 0x8d, 0xfb, 0x8d,
0x7b, 0xe1, 0x4b, 0x9e, 0xdf, 0x08, 0x5c, 0xb2,
0x28, 0xc0, 0x79, 0x45, 0xd1, 0xf3, 0x9c, 0x70,
0xd8, 0xaf, 0x50, 0x1c, 0xc3, 0x10, 0x24, 0x84,
0xc1, 0xb1, 0x36, 0x3f, 0xd4, 0xbf, 0x10, 0x18,
0xf9, 0xd0, 0x72, 0xea, 0xce, 0xbf, 0x34, 0x8e,
0xb5, 0x97, 0xcb, 0x8a, 0x5e, 0x8e, 0x7d, 0xed,
0x1f, 0xe3, 0xa9, 0xde, 0x5b, 0x3f, 0xc9, 0x33,
0x4c, 0x9b, 0x3e, 0xd8, 0x29, 0x61, 0x6b, 0x30,
0xba, 0xa1, 0x36, 0xbd, 0x22, 0x33, 0xa1, 0x25,
0x73, 0xab, 0x5f, 0x6f, 0x35, 0x48, 0xf1, 0xad,
0x96, 0x5f, 0x0d, 0x0c, 0xe5, 0xe9, 0x8d, 0xf9,
0xed, 0x0c, 0xcf, 0x50, 0x3c, 0x24, 0x34, 0x9b,
0x9e, 0xbc, 0xf9, 0xfa, 0x19, 0x51, 0x37, 0x03,
0x5c, 0xd0, 0x25, 0x1f, 0xe6, 0xb2, 0xf7, 0xff,
0x96, 0xb0, 0x61, 0x42, 0xbb, 0xc5, 0x64, 0x5f,
0x3d, 0xaf, 0x6f, 0x14, 0xcc, 0x92, 0x74, 0x6a,
0x06, 0xfa, 0xb2, 0xd9, 0xe1, 0x4d, 0x42, 0x76,
0xab, 0x88, 0xe3, 0x08, 0xa2, 0xad, 0x00, 0xb6,
0xf7, 0x78, 0x0c, 0xba, 0x08, 0x71, 0xbc, 0x8d,
0x98, 0x43, 0x12, 0x63, 0x8d, 0x5e, 0x1f, 0x49,
0xb9, 0x5f, 0x0d, 0x55, 0x1a, 0x90, 0x63, 0x4c,
0xd8, 0xe8, 0x0b, 0x9f, 0x3d, 0x10, 0xb4, 0xf9,
0x1b, 0x44, 0x3f, 0x43, 0xad, 0x35, 0x42, 0x3d,
0x3d, 0x21, 0x8e, 0xa8, 0x08, 0x28, 0x47, 0x19,
0x14, 0x28, 0x1c, 0x95, 0xb7, 0x5d, 0x02, 0x03,
0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x17,
0xd3, 0x1d, 0x45, 0xcd, 0x2b, 0xa7, 0x6a, 0xde,
0x07, 0x31, 0x97, 0xee, 0xca, 0x22, 0x6b, 0x0a,
0x05, 0xf7, 0xf7, 0x63, 0xad, 0x59, 0x60, 0x50,
0x36, 0x6b, 0xab, 0x2e, 0x1e, 0x48, 0xfb, 0x2c,
0xa4, 0x98, 0x82, 0xd8, 0xf1, 0x6f, 0xb6, 0x43,
0xdc, 0xb2, 0x80, 0x7b, 0xa5, 0x9b, 0x72, 0x25,
0x52, 0x86, 0x8f, 0x83, 0x04, 0x8f, 0x0d, 0x48,
0x40, 0xd2, 0x81, 0x04, 0xf6, 0x9b, 0x42, 0xee,
0x21, 0x50, 0x62, 0x02, 0x49, 0x3b, 0x66, 0x2e,
0xe4, 0xe4, 0x56, 0xee, 0x8f, 0xb5, 0x18, 0x1c,
0x0e, 0xb4, 0x1e, 0x9f, 0x8f, 0x4c, 0x70, 0x6e,
0xbb, 0x95, 0xa9, 0xc7, 0xf1, 0x8d, 0xda, 0x3a,
0xe7, 0x1f, 0xaf, 0xc8, 0x80, 0x53, 0xe4, 0xbb,
0x39, 0x97, 0xdd, 0xbf, 0x2f, 0x2c, 0x56, 0xab,
0x86, 0x90, 0x2b, 0xdd, 0xd4, 0x4e, 0xd4, 0xd5,
0x3d, 0x17, 0xca, 0x8a, 0x5f, 0xb2, 0x41, 0xa1,
0xc6, 0x52, 0x80, 0xe5, 0xf0, 0x7a, 0xda, 0x35,
0xa5, 0x36, 0xb9, 0x61, 0x15, 0x60, 0x39, 0x2f,
0x04, 0x1f, 0x6e, 0xee, 0x99, 0xee, 0xa5, 0x21,
0xcc, 0x4f, 0xa3, 0x4e, 0x06, 0xc5, 0xbc, 0xa5,
0x34, 0xd6, 0x10, 0x57, 0x36, 0x85, 0xf7, 0x0a,
0x34, 0xfb, 0xa5, 0x6b, 0x71, 0x9c, 0x4a, 0x43,
0x4a, 0xd0, 0xcb, 0xb4, 0x9a, 0xac, 0x4f, 0x9a,
0x29, 0xe8, 0x68, 0x15, 0x00, 0xe4, 0x6c, 0x34,
0xc3, 0x73, 0x7e, 0xb5, 0x16, 0x2a, 0x17, 0x37,
0xc0, 0xb6, 0xaf, 0x81, 0xb4, 0x73, 0xf2, 0xd3,
0x9f, 0xaa, 0x40, 0x73, 0x28, 0x0d, 0xfd, 0xb4,
0x67, 0x6e, 0x82, 0xa8, 0x13, 0x34, 0xc0, 0x54,
0x88, 0xaf, 0x85, 0x6f, 0xd8, 0x33, 0x84, 0x82,
0xb5, 0xd0, 0x5f, 0x7f, 0x21, 0xca, 0x6d, 0x86,
0x74, 0xb3, 0x89, 0x81, 0x19, 0x45, 0x47, 0x38,
0x41, 0x53, 0x47, 0x86, 0xc6, 0xcd, 0x9d, 0x02,
0x81, 0x81, 0x00, 0xfd, 0x90, 0x23, 0xf9, 0xba,
0xc5, 0x69, 0x7d, 0x11, 0xed, 0x69, 0x57, 0x73,
0x1d, 0x06, 0xe8, 0x1b, 0x37, 0x00, 0x69, 0x95,
0xc5, 0x63, 0x86, 0x3f, 0xda, 0xb4, 0x11, 0xad,
0x69, 0x55, 0xf4, 0x76, 0x3c, 0xa0, 0x95, 0x65,
0x60, 0x29, 0xb9, 0x69, 0x79, 0xca, 0x74, 0x50,
0xe3, 0x98, 0xc7, 0x90, 0xd7, 0xb8, 0xd4, 0xc5,
0x51, 0x10, 0xa3, 0x10, 0x72, 0xf3, 0xdc, 0x91,
0xb4, 0xee, 0xdd, 0x9a, 0x57, 0xf1, 0x1b, 0x0e,
0xba, 0x0f, 0x67, 0x1a, 0x94, 0x86, 0x36, 0x69,
0x20, 0xd5, 0x6b, 0x80, 0x50, 0x7d, 0x20, 0x53,
0xeb, 0xed, 0x8a, 0xc5, 0xbc, 0xcb, 0x13, 0xb9,
0x0d, 0x49, 0x22, 0x7c, 0xeb, 0xa6, 0x97, 0x5a,
0x5b, 0x92, 0x3a, 0x3d, 0x93, 0x5b, 0x86, 0x2c,
0x75, 0x0b, 0xfa, 0x68, 0xa6, 0xc1, 0x68, 0x07,
0x37, 0x01, 0x9b, 0xd1, 0x51, 0xfe, 0xc0, 0x4c,
0x2d, 0x15, 0x9f, 0x02, 0x81, 0x81, 0x00, 0xf4,
0xbe, 0xc1, 0x32, 0xad, 0xca, 0x28, 0x37, 0x7c,
0x17, 0x99, 0xde, 0x64, 0x9b, 0xc1, 0xf8, 0x23,
0x6a, 0xde, 0xd8, 0x01, 0x59, 0x09, 0x10, 0x67,
0xb8, 0x27, 0xc5, 0xe6, 0xee, 0xf8, 0x16, 0x7c,
0x46, 0xa0, 0x0b, 0x00, 0xf9, 0xff, 0x72, 0x4b,
0xde, 0x65, 0x65, 0xb6, 0xaa, 0x44, 0x1a, 0xbc,
0xdf, 0x13, 0x15, 0x08, 0x80, 0xa5, 0xb4, 0xdd,
0xcd, 0xe0, 0x34, 0x4a, 0x85, 0x31, 0x82, 0x17,
0x57, 0x5a, 0xea, 0x21, 0x38, 0x26, 0xdf, 0x48,
0x59, 0x1d, 0x58, 0x5b, 0x9f, 0x04, 0x12, 0xee,
0x5b, 0xa2, 0xa9, 0xb3, 0xfe, 0x83, 0xa7, 0xda,
0x47, 0xc6, 0xfb, 0x89, 0x77, 0x1f, 0x3a, 0xbc,
0x7c, 0xc7, 0x13, 0xc9, 0xb8, 0xdc, 0xb0, 0x9e,
0xa7, 0x2a, 0xa5, 0x2c, 0x3b, 0x96, 0xe2, 0x2e,
0xc0, 0xcf, 0xfa, 0x0c, 0xe0, 0x2d, 0xad, 0xaa,
0x7f, 0x85, 0x4b, 0x6f, 0x04, 0xf9, 0x83, 0x02,
0x81, 0x81, 0x00, 0xca, 0x8f, 0xd2, 0xdd, 0x96,
0xc2, 0x4c, 0x52, 0x58, 0xf7, 0x03, 0x77, 0x94,
0x03, 0x75, 0x58, 0x09, 0x1d, 0xb8, 0x5b, 0xa1,
0x05, 0x4e, 0x4b, 0x9a, 0x49, 0x5a, 0x1e, 0xe1,
0x1c, 0xcc, 0x48, 0xfe, 0x07, 0xd2, 0xf5, 0x66,
0x46, 0x1b, 0x2e, 0xfe, 0xbf, 0x07, 0xe8, 0x42,
0x12, 0x80, 0x23, 0xb5, 0x67, 0x50, 0x45, 0xd1,
0xd7, 0xbf, 0xe5, 0xb4, 0xa7, 0x50, 0x7f, 0x3d,
0x7b, 0x80, 0x73, 0x51, 0xf0, 0xbd, 0x31, 0x33,
0x63, 0x9a, 0x18, 0x70, 0xd8, 0x84, 0x1b, 0x85,
0x82, 0x70, 0x5c, 0x6f, 0xe6, 0x5c, 0xff, 0x6d,
0x6b, 0x85, 0x99, 0x9d, 0xfc, 0x03, 0x73, 0x9f,
0x1a, 0xa8, 0xf9, 0x3f, 0x38, 0x76, 0x1e, 0x65,
0x55, 0xd0, 0x0c, 0x6c, 0xd2, 0x82, 0x84, 0x3e,
0x91, 0xc6, 0xde, 0xe5, 0xa9, 0x89, 0xca, 0x54,
0x31, 0x32, 0x3c, 0xcb, 0x4c, 0xa8, 0xa9, 0xf0,
0x70, 0xf7, 0xdb, 0x02, 0x81, 0x80, 0x62, 0x16,
0xd9, 0xa3, 0x90, 0x17, 0x87, 0x8a, 0xc5, 0x47,
0x48, 0x39, 0xe3, 0xa4, 0xb1, 0x56, 0xdc, 0x0b,
0x07, 0x09, 0x17, 0x71, 0x31, 0xba, 0xcb, 0x76,
0xf9, 0x29, 0xcd, 0xe6, 0x54, 0xb3, 0xde, 0x57,
0x07, 0xe9, 0xa1, 0x18, 0x91, 0x12, 0xa3, 0xe9,
0x9c, 0x45, 0xe9, 0xb1, 0xcf, 0xdd, 0xcf, 0x78,
0xb0, 0x53, 0x2b, 0xb7, 0x33, 0xb2, 0x8b, 0x7a,
0xe9, 0xb2, 0xcb, 0x73, 0x1a, 0x66, 0x83, 0x28,
0x55, 0x9d, 0xa4, 0x76, 0xb6, 0xcd, 0xa2, 0x57,
0x64, 0xf5, 0x76, 0xb3, 0x02, 0x94, 0xfb, 0xc6,
0xea, 0x28, 0x8d, 0xa5, 0x21, 0xea, 0xf2, 0x06,
0xf6, 0x6e, 0xf5, 0xa7, 0x32, 0x72, 0xfd, 0xfc,
0x1c, 0x65, 0x87, 0xe1, 0x79, 0x41, 0xa8, 0x34,
0x63, 0x59, 0x13, 0xa3, 0x46, 0x53, 0x9c, 0x5d,
0x56, 0x7d, 0x67, 0x0f, 0xa9, 0xff, 0x02, 0x68,
0x5d, 0x69, 0xe0, 0x32, 0xe4, 0x35, 0x02, 0x81,
0x80, 0x55, 0xf8, 0x25, 0x84, 0x94, 0xad, 0x50,
0xab, 0x49, 0x38, 0x30, 0xaf, 0xde, 0x53, 0xdc,
0x27, 0x08, 0x25, 0x27, 0x5a, 0xd2, 0xe5, 0x21,
0x50, 0xde, 0x6d, 0x6b, 0xc7, 0x17, 0xae, 0x21,
0xb6, 0xcb, 0xe9, 0x24, 0x7c, 0x76, 0x32, 0xe3,
0xcb, 0xba, 0xee, 0x61, 0xd2, 0x79, 0xf2, 0x88,
0x12, 0x1c, 0x9f, 0x29, 0xb3, 0x6a, 0x73, 0x16,
0xfc, 0x35, 0xcf, 0xe7, 0x68, 0xec, 0x47, 0xf7,
0xfb, 0x2d, 0x18, 0xff, 0xa8, 0xbf, 0xe1, 0xe8,
0x64, 0xa0, 0x98, 0x4a, 0x70, 0x07, 0x5d, 0xb1,
0x8e, 0x6e, 0x15, 0x4e, 0x0d, 0x28, 0x61, 0xb1,
0x37, 0x21, 0xcb, 0xba, 0x1d, 0x1b, 0xff, 0x06,
0x9f, 0xbe, 0xbc, 0xa9, 0x93, 0x77, 0x07, 0xc1,
0xc0, 0x1a, 0x4b, 0x13, 0xee, 0xa3, 0xdb, 0x7e,
0x99, 0x94, 0xcc, 0x5b, 0x88, 0xfb, 0xb9, 0x77,
0x3c, 0x81, 0x80, 0x5d, 0xef, 0x3e, 0xf8, 0x6e,
0xfa};
static const uint8_t RSA3072[] = {
0x30, 0x82, 0x06, 0xff, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x06, 0xe9, 0x30, 0x82, 0x06, 0xe5, 0x02, 0x01,
0x00, 0x02, 0x82, 0x01, 0x81, 0x00, 0xc7, 0x02,
0x17, 0x90, 0x02, 0x4e, 0x0a, 0x00, 0x9b, 0x74,
0x3a, 0x14, 0x72, 0x0c, 0x81, 0x07, 0xe8, 0xdb,
0xcb, 0x07, 0xfd, 0x4b, 0xc5, 0xed, 0xe0, 0x56,
0x22, 0xe7, 0x49, 0x76, 0x8b, 0x21, 0xaa, 0xa5,
0xac, 0x11, 0xa7, 0xfe, 0x0c, 0xdc, 0x78, 0x3f,
0xf2, 0xe9, 0xa2, 0xa8, 0xf0, 0xd2, 0x0f, 0x64,
0x78, 0xd5, 0x65, 0x75, 0x73, 0x13, 0x8f, 0xaf,
0x2d, 0xf3, 0xbc, 0x0e, 0x5a, 0x43, 0xd4, 0x5b,
0xa8, 0xb8, 0x83, 0x3f, 0x39, 0xd8, 0xa3, 0xbe,
0xfa, 0xc2, 0xf8, 0xe1, 0x2e, 0x1a, 0x71, 0x54,
0xfc, 0x03, 0xd5, 0x84, 0xde, 0x11, 0x38, 0xe2,
0xf2, 0x9f, 0xe9, 0xb7, 0x25, 0x9f, 0x84, 0xe7,
0x0a, 0x6c, 0x3e, 0x1e, 0xb0, 0x39, 0xa2, 0xa2,
0x68, 0x12, 0xb3, 0x8a, 0x48, 0xd0, 0xbd, 0x23,
0x95, 0xde, 0x96, 0x9d, 0x73, 0xe8, 0x8b, 0xf9,
0x0d, 0x7b, 0x70, 0xc6, 0xb8, 0x5b, 0x39, 0x3d,
0x7e, 0x78, 0xad, 0x11, 0x47, 0x8c, 0x72, 0x4e,
0x55, 0xec, 0xaa, 0xbd, 0x54, 0xfd, 0x1a, 0x02,
0xea, 0x9f, 0x47, 0xb7, 0x1e, 0xa1, 0x5d, 0xc9,
0x3f, 0x62, 0x85, 0x1b, 0xf8, 0x6e, 0xf2, 0x49,
0xfb, 0x55, 0x85, 0x15, 0x94, 0x0c, 0x14, 0x91,
0x0b, 0xf4, 0x27, 0x96, 0xa8, 0xb4, 0x49, 0x82,
0x1b, 0xba, 0xc9, 0x62, 0x03, 0x0e, 0x78, 0x44,
0x15, 0xca, 0x6e, 0x31, 0x03, 0x52, 0x06, 0x26,
0x37, 0x6f, 0x0e, 0x0d, 0xca, 0x54, 0x2f, 0xc7,
0x58, 0xb4, 0x64, 0xee, 0xa5, 0xa4, 0xbe, 0x71,
0xdb, 0xc0, 0x8b, 0x05, 0xf3, 0xbd, 0xd3, 0x1c,
0x6c, 0x75, 0x5d, 0x29, 0x0d, 0x5a, 0x82, 0x74,
0x6a, 0x24, 0x72, 0xef, 0xfb, 0xaf, 0xe5, 0x3c,
0x38, 0xbf, 0x81, 0x71, 0x8f, 0x19, 0x85, 0x4e,
0xc8, 0x8b, 0x13, 0xf2, 0x47, 0x7f, 0xd3, 0x3c,
0xad, 0x34, 0xfe, 0xc3, 0x47, 0x06, 0xe8, 0x0c,
0xfc, 0xc6, 0x09, 0x31, 0x28, 0x35, 0xfe, 0xe6,
0x48, 0xf7, 0x63, 0xff, 0x1a, 0x44, 0x55, 0x7c,
0x23, 0xa0, 0x30, 0x23, 0x67, 0xe2, 0x35, 0xfb,
0x55, 0xd3, 0x86, 0xbd, 0x46, 0x66, 0x0f, 0x01,
0x29, 0xc7, 0x79, 0xbe, 0x44, 0x1b, 0xa4, 0xda,
0x53, 0xdb, 0x2c, 0x36, 0x16, 0xc6, 0xfe, 0xef,
0x6a, 0x41, 0xb0, 0x7e, 0xb4, 0x0e, 0x64, 0x70,
0x9b, 0x11, 0x3f, 0x19, 0xe8, 0x3a, 0x8f, 0x13,
0xc8, 0xd3, 0xac, 0x5e, 0xeb, 0x54, 0x11, 0x68,
0x9a, 0x7c, 0xec, 0xaf, 0x3e, 0xa0, 0xca, 0x48,
0xff, 0xa5, 0x7f, 0x60, 0x51, 0x9e, 0x55, 0x0b,
0x94, 0x00, 0x51, 0x66, 0x49, 0x37, 0x53, 0x36,
0x5d, 0xe5, 0x7c, 0x80, 0xdd, 0x44, 0x56, 0xa0,
0x9f, 0x19, 0x34, 0x21, 0x81, 0x53, 0x25, 0xb6,
0x96, 0x62, 0x77, 0xda, 0xe0, 0xe0, 0xdc, 0x70,
0xfa, 0x8e, 0xb5, 0xbc, 0x72, 0xe7, 0x02, 0x03,
0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x80, 0x08,
0xe8, 0xc9, 0x11, 0x43, 0x69, 0x26, 0xfd, 0x7b,
0xf8, 0x2a, 0x19, 0x7c, 0x39, 0x9f, 0x15, 0x31,
0x91, 0x95, 0x77, 0x58, 0x19, 0xaa, 0x54, 0xc9,
0xf4, 0x51, 0x3f, 0xb5, 0x84, 0x3f, 0x1a, 0x54,
0xbf, 0x72, 0x02, 0xa0, 0x58, 0xb9, 0x4e, 0xad,
0x7b, 0x7f, 0x6e, 0x82, 0x3f, 0xb9, 0xf8, 0x4d,
0x84, 0x1b, 0xfc, 0xc1, 0xbc, 0x0e, 0x58, 0xd3,
0xd7, 0xed, 0xe0, 0xb9, 0x8c, 0x92, 0xf1, 0xf2,
0x71, 0xe0, 0x0d, 0xd2, 0xa2, 0x63, 0xfe, 0x94,
0xe6, 0x19, 0xe7, 0xdc, 0xa8, 0x88, 0x1d, 0xda,
0xf1, 0x09, 0x0f, 0x4a, 0xe1, 0xd5, 0xe7, 0x43,
0x7a, 0xb5, 0x8d, 0xff, 0x32, 0x99, 0xd6, 0x98,
0x66, 0x97, 0x8a, 0xdd, 0x05, 0x16, 0xb2, 0x9d,
0xdb, 0x53, 0x79, 0x72, 0xdc, 0x40, 0x02, 0x48,
0x55, 0x6d, 0x82, 0x37, 0x8f, 0xf8, 0xfe, 0x72,
0x35, 0xc6, 0x2a, 0xbe, 0x93, 0xc6, 0xf1, 0x1e,
0x90, 0xe8, 0x36, 0x92, 0xd8, 0xf1, 0x31, 0x12,
0x74, 0xfb, 0x57, 0xcb, 0x15, 0x0a, 0xd7, 0x01,
0xf1, 0x1b, 0x7b, 0xe2, 0x04, 0x0a, 0xb5, 0x02,
0xb3, 0xdd, 0xc8, 0x95, 0x58, 0xf9, 0x38, 0x4e,
0x54, 0x8d, 0x91, 0xf8, 0x91, 0x4c, 0xbd, 0x75,
0xb6, 0x40, 0xa8, 0xbf, 0x94, 0xf9, 0x1c, 0x89,
0x25, 0xf0, 0x03, 0xde, 0xbc, 0x2a, 0x92, 0xdd,
0x43, 0x7f, 0x0e, 0x3e, 0xfc, 0xa6, 0xbf, 0x53,
0x09, 0x4c, 0x38, 0x0d, 0x81, 0x7d, 0x54, 0xee,
0x3a, 0x1d, 0x70, 0xed, 0x1e, 0x3e, 0xc0, 0x5e,
0xfe, 0x35, 0x96, 0xe9, 0x58, 0xf3, 0xa6, 0xf2,
0x3b, 0xd3, 0xc3, 0x6a, 0xbd, 0xbf, 0x0d, 0x72,
0x42, 0x32, 0x41, 0xc3, 0xb3, 0x82, 0xa2, 0x64,
0x89, 0x91, 0xad, 0x0a, 0x91, 0x55, 0x20, 0x17,
0x86, 0x61, 0xae, 0x67, 0x45, 0xa3, 0xe3, 0xb7,
0x2c, 0xcc, 0x96, 0xcb, 0xb2, 0x5d, 0x1f, 0x0d,
0xc3, 0x2f, 0x22, 0x46, 0x6b, 0xb7, 0x10, 0x76,
0x97, 0xdd, 0x14, 0x37, 0xb7, 0x5a, 0x0b, 0xfa,
0xaa, 0xd5, 0x7c, 0x99, 0x40, 0xd0, 0x81, 0xdd,
0xd2, 0x20, 0x49, 0x40, 0x57, 0xeb, 0x13, 0xbe,
0xcc, 0xa1, 0x1c, 0xf3, 0x9d, 0x14, 0x91, 0xf2,
0xf3, 0xfc, 0xd5, 0x89, 0x20, 0x41, 0x86, 0x34,
0xd5, 0x3d, 0x50, 0x85, 0xa8, 0xe4, 0x0f, 0x9d,
0x9c, 0xc7, 0x96, 0x90, 0xa1, 0x9f, 0x53, 0xba,
0x29, 0x3f, 0x1c, 0x6e, 0xcf, 0xa3, 0x3e, 0x59,
0x8a, 0x8e, 0x78, 0xb9, 0xf3, 0x13, 0xc6, 0x73,
0xe4, 0xe8, 0xb5, 0x23, 0xa6, 0xb8, 0x19, 0x6b,
0x28, 0x2a, 0x97, 0x6d, 0xc8, 0x5b, 0x6c, 0xa9,
0xfc, 0x58, 0x2c, 0xa5, 0x03, 0x2f, 0x1c, 0x6f,
0x43, 0x56, 0xb8, 0xfa, 0xa9, 0xb8, 0x54, 0x8d,
0x8b, 0x4a, 0xe6, 0xf8, 0xc4, 0x82, 0x83, 0xd7,
0xb1, 0x10, 0xe6, 0x5b, 0xb2, 0x17, 0x71, 0x02,
0x81, 0xc1, 0x00, 0xf6, 0x81, 0x91, 0xc5, 0x86,
0x54, 0x6e, 0x00, 0x67, 0x01, 0xe0, 0xb5, 0x1e,
0x5f, 0x8d, 0xec, 0x2b, 0xf1, 0x46, 0xb3, 0xf1,
0x33, 0x47, 0x9a, 0x52, 0x1a, 0x31, 0x2b, 0x08,
0x60, 0x64, 0xe4, 0x30, 0x2c, 0x12, 0xe9, 0xe2,
0x3e, 0x6f, 0x7a, 0xe7, 0xc5, 0x44, 0x86, 0x13,
0x31, 0x9d, 0x9c, 0x05, 0xf4, 0x67, 0xbe, 0x95,
0xf0, 0x78, 0x52, 0x9b, 0x0b, 0x19, 0x6d, 0x75,
0xdb, 0x02, 0x74, 0x10, 0x66, 0x25, 0x0c, 0xdd,
0xd1, 0xd4, 0x12, 0x7f, 0xa3, 0x20, 0x9c, 0x66,
0x78, 0x96, 0xae, 0xe9, 0x8c, 0x2e, 0xc3, 0x9f,
0xfe, 0x5b, 0xa2, 0x65, 0x4e, 0xfe, 0x95, 0xe9,
0x04, 0xe0, 0xa7, 0x49, 0x26, 0x4c, 0xd1, 0xb0,
0xb4, 0x03, 0x11, 0xdc, 0xa3, 0xc8, 0x4b, 0x1c,
0xc8, 0x74, 0xe1, 0x9d, 0xb2, 0xb1, 0xcb, 0x70,
0x2d, 0xd3, 0x0e, 0xef, 0x6c, 0x27, 0x95, 0x10,
0x0d, 0xd5, 0xad, 0x88, 0x80, 0x7e, 0xc0, 0x0f,
0xcc, 0x1b, 0xe5, 0xb8, 0x4d, 0xc2, 0xd2, 0x85,
0xc3, 0xb2, 0x8f, 0x4b, 0xce, 0x9f, 0x7c, 0x36,
0x51, 0x4a, 0xb6, 0x72, 0x43, 0x7c, 0xe2, 0xb0,
0x4e, 0x8a, 0x04, 0xa1, 0xd4, 0x2b, 0x3c, 0xe8,
0x54, 0xff, 0x05, 0x00, 0x29, 0xa4, 0xb7, 0xc1,
0x75, 0xe0, 0x00, 0x19, 0xbc, 0x2e, 0xcd, 0xeb,
0x40, 0x93, 0x39, 0x69, 0xc4, 0x0e, 0x8c, 0x3b,
0x0e, 0x52, 0x25, 0x02, 0x81, 0xc1, 0x00, 0xce,
0xac, 0x37, 0x41, 0xb9, 0x26, 0x2d, 0xdf, 0x40,
0xbd, 0x78, 0x6e, 0x09, 0xba, 0x8e, 0x54, 0xc6,
0xfa, 0x56, 0x21, 0x1c, 0x5d, 0x7d, 0xe7, 0x4f,
0x35, 0x03, 0x57, 0x06, 0xad, 0xa0, 0xae, 0x0c,
0x82, 0xee, 0x01, 0x54, 0xba, 0x11, 0xb6, 0x5f,
0x04, 0x48, 0xfb, 0x1c, 0x5f, 0xba, 0xeb, 0x8d,
0xcb, 0xb3, 0x9e, 0xdc, 0xef, 0x35, 0xd7, 0x9e,
0x68, 0xbd, 0xde, 0xe4, 0xc5, 0x4b, 0x9a, 0xca,
0xe4, 0x5d, 0x71, 0x23, 0x2b, 0xe4, 0xf6, 0x81,
0x27, 0x43, 0xeb, 0x96, 0x14, 0xc1, 0xc4, 0x20,
0x7a, 0xd9, 0x83, 0x80, 0x24, 0x32, 0x3b, 0x6c,
0x81, 0xed, 0x32, 0x0b, 0x35, 0x38, 0x3a, 0x82,
0x1d, 0x2e, 0xd7, 0x02, 0x46, 0x71, 0x49, 0x58,
0x02, 0xe8, 0xf7, 0x05, 0xac, 0x92, 0x7f, 0xc9,
0x4a, 0x7e, 0x5f, 0x4e, 0x53, 0xde, 0xaf, 0x63,
0x2e, 0xec, 0xff, 0x91, 0x47, 0x0f, 0x1e, 0x15,
0xac, 0x21, 0xf7, 0xdf, 0x3a, 0x81, 0x6d, 0x94,
0xe1, 0x9a, 0x7a, 0x06, 0xf5, 0x84, 0x9b, 0x08,
0x91, 0x5b, 0x9e, 0xb2, 0x4c, 0x4c, 0xde, 0xe0,
0x5f, 0xee, 0xaa, 0x6c, 0x3c, 0x76, 0x57, 0x0a,
0xa4, 0x7f, 0x01, 0x79, 0x23, 0x4e, 0x7c, 0xe7,
0xd9, 0x0d, 0x33, 0x15, 0x3f, 0xb2, 0xec, 0xf8,
0xcb, 0xc5, 0xca, 0x53, 0x68, 0xfb, 0x15, 0x05,
0x01, 0xae, 0x1c, 0x41, 0x0d, 0xd5, 0x1b, 0x02,
0x81, 0xc1, 0x00, 0xcc, 0x3d, 0x76, 0xa6, 0x0e,
0x32, 0x8e, 0x21, 0xcf, 0x37, 0x03, 0x13, 0x8d,
0xe2, 0xe6, 0x18, 0x34, 0x20, 0x68, 0xd0, 0x56,
0x9c, 0x82, 0x4b, 0x1e, 0x93, 0x8d, 0x01, 0x76,
0xa3, 0x47, 0x74, 0xb9, 0x65, 0x0b, 0x16, 0xb5,
0xd9, 0xbd, 0x4c, 0x3c, 0x14, 0x7a, 0x3e, 0x0c,
0x51, 0x23, 0xa1, 0x4e, 0x5d, 0xbe, 0x47, 0x6e,
0xbc, 0x1b, 0x35, 0x76, 0x38, 0xb0, 0x0c, 0xbd,
0x85, 0x84, 0x76, 0xdd, 0xcf, 0x84, 0x0b, 0x31,
0x0e, 0xd5, 0x83, 0xae, 0x35, 0x5e, 0xa3, 0xb7,
0x53, 0x5a, 0xa5, 0xf9, 0xe3, 0xa8, 0x2b, 0x75,
0xb8, 0xad, 0xfb, 0xd3, 0xac, 0xab, 0xcb, 0x51,
0x92, 0x35, 0x00, 0xe5, 0xde, 0xd1, 0xef, 0x3b,
0x55, 0x2a, 0xe5, 0xf5, 0xc5, 0xce, 0x02, 0x4e,
0x0a, 0xd8, 0xac, 0xc6, 0x98, 0x74, 0x2f, 0x76,
0xf6, 0xc0, 0xd4, 0xb3, 0x13, 0x0d, 0x88, 0xb8,
0x10, 0x7e, 0x66, 0x95, 0x9e, 0xc1, 0x66, 0x28,
0xb0, 0x98, 0xbc, 0xb1, 0x03, 0xdc, 0xd3, 0xc8,
0xf8, 0xe8, 0x4d, 0x4a, 0x26, 0x1c, 0x86, 0x32,
0x0b, 0x10, 0xb8, 0x31, 0xdc, 0x30, 0xf1, 0x31,
0xdb, 0x21, 0x07, 0xcd, 0x7d, 0x99, 0x85, 0x91,
0x8a, 0x3a, 0xf1, 0xcd, 0xbc, 0xb3, 0x39, 0x7d,
0x15, 0x49, 0x4f, 0x4c, 0x03, 0x5b, 0x54, 0x4a,
0x02, 0xea, 0xf8, 0xba, 0xe5, 0x32, 0x98, 0x85,
0xa5, 0xcb, 0xf1, 0x02, 0x81, 0xc1, 0x00, 0x86,
0xab, 0x11, 0x16, 0x72, 0x5e, 0xbe, 0x65, 0x4a,
0xfa, 0x2b, 0x0f, 0x08, 0xa7, 0xd7, 0x36, 0xc6,
0xb1, 0x38, 0x8e, 0x3a, 0xbd, 0x70, 0xdc, 0xd8,
0x6f, 0xe2, 0xcd, 0x42, 0x3c, 0xc1, 0x06, 0xa8,
0x80, 0x68, 0x35, 0xd5, 0xcf, 0xa8, 0xda, 0xfc,
0xee, 0xfd, 0xdf, 0x22, 0x8d, 0xfe, 0x6e, 0x9e,
0xe6, 0xad, 0x14, 0x47, 0x42, 0x58, 0x03, 0x37,
0xe5, 0x68, 0x53, 0x65, 0x1e, 0x6a, 0x35, 0x63,
0x1f, 0x8b, 0x03, 0xbd, 0xb7, 0x4c, 0x6a, 0x93,
0x9d, 0xd2, 0x54, 0x20, 0x67, 0x46, 0x1b, 0x56,
0x4e, 0xb6, 0x8d, 0x49, 0x62, 0x4c, 0x99, 0x0c,
0x0b, 0x5d, 0x53, 0xce, 0x99, 0xcf, 0x19, 0xd0,
0xce, 0xd3, 0x46, 0xa6, 0xe4, 0xdf, 0xcc, 0xba,
0xdc, 0xaa, 0x90, 0xcb, 0xd1, 0xb7, 0x64, 0x2c,
0xf5, 0xad, 0x82, 0xcc, 0xb7, 0x39, 0xd3, 0x6e,
0xfd, 0x94, 0xd0, 0xb3, 0x09, 0x6a, 0x80, 0x5f,
0xfe, 0xd9, 0xe3, 0x7a, 0x41, 0xd5, 0x34, 0x62,
0x5e, 0xdf, 0x19, 0xc4, 0x8f, 0x16, 0xe9, 0x2e,
0x9c, 0x08, 0xe7, 0x4f, 0xa7, 0x08, 0x2f, 0xf2,
0x64, 0x90, 0x4f, 0xdc, 0x57, 0x49, 0x85, 0x4e,
0x1a, 0x01, 0xe8, 0x23, 0xd7, 0x2d, 0xbd, 0x96,
0x15, 0x88, 0xd4, 0x50, 0x74, 0x41, 0x52, 0xc8,
0x8b, 0x7f, 0x46, 0x67, 0x33, 0x70, 0xe8, 0x31,
0x6a, 0xf6, 0xd8, 0xd2, 0x4b, 0x01, 0x21, 0x02,
0x81, 0xc1, 0x00, 0xb8, 0xeb, 0x06, 0x5f, 0xc3,
0xde, 0x34, 0x1e, 0x4f, 0x0b, 0xff, 0x62, 0xc3,
0x3d, 0x2b, 0x23, 0xbd, 0x28, 0xfd, 0x3c, 0x24,
0x15, 0x10, 0x50, 0x3d, 0x97, 0x0d, 0xfa, 0xc7,
0xd6, 0x62, 0x92, 0x26, 0xc7, 0xc6, 0x5d, 0x33,
0xfb, 0xaf, 0x35, 0x9d, 0x31, 0xd5, 0xfb, 0x9d,
0x93, 0x47, 0x48, 0x82, 0xe1, 0x28, 0xe1, 0xdd,
0x0b, 0xcf, 0xd0, 0xe1, 0x8e, 0xaf, 0x6c, 0xd2,
0xee, 0x2a, 0x99, 0xd9, 0x9c, 0xdb, 0xa7, 0x29,
0x7a, 0xfe, 0x44, 0x79, 0x41, 0x60, 0xa8, 0x4c,
0x74, 0xf2, 0xcc, 0xe4, 0x88, 0x32, 0x31, 0x41,
0x9d, 0xda, 0xf8, 0xa3, 0x6e, 0x64, 0xbf, 0x41,
0xfb, 0xea, 0x11, 0x74, 0x10, 0x66, 0xb4, 0x8b,
0x7c, 0x65, 0x5f, 0x1b, 0xd6, 0xa4, 0xa1, 0xee,
0xd2, 0xfd, 0x6b, 0x8e, 0x7e, 0x52, 0x76, 0xf0,
0x7e, 0xdb, 0x11, 0x2e, 0xc8, 0xcf, 0xd5, 0x57,
0x08, 0xa0, 0x1c, 0x89, 0xf0, 0x9d, 0xee, 0x88,
0x13, 0x80, 0x34, 0xc8, 0xd3, 0xa6, 0x9d, 0x55,
0xb0, 0x5d, 0xe4, 0x0d, 0xae, 0xeb, 0x42, 0x4a,
0x8a, 0x69, 0xb2, 0x58, 0xc0, 0x68, 0x88, 0xbb,
0x6b, 0xcd, 0xf1, 0x37, 0x9a, 0x3f, 0x15, 0xe6,
0x1f, 0x07, 0xb6, 0xe7, 0xf6, 0x23, 0x3d, 0xba,
0xee, 0x23, 0x0d, 0x01, 0x89, 0xc1, 0xe4, 0xe8,
0xe4, 0xf4, 0x5c, 0x5f, 0x22, 0xbc, 0x67, 0xba,
0xad, 0x6a, 0x10};
static const uint8_t RSA4096[] = {
0x30, 0x82, 0x09, 0x43, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x09, 0x2d, 0x30, 0x82, 0x09, 0x29, 0x02, 0x01,
0x00, 0x02, 0x82, 0x02, 0x01, 0x00, 0xe5, 0x26,
0x35, 0xe2, 0x8f, 0x2d, 0x4d, 0x98, 0x4e, 0x78,
0xa8, 0x3d, 0xa2, 0xca, 0xa4, 0x18, 0x55, 0x5a,
0x2d, 0x8d, 0x39, 0x12, 0x9c, 0x41, 0xc1, 0xd8,
0x15, 0x73, 0x3b, 0xb7, 0x08, 0xae, 0x10, 0x3e,
0x2a, 0x3c, 0x09, 0xdb, 0xd7, 0xd1, 0x13, 0x2c,
0x2e, 0x47, 0xfe, 0x17, 0x34, 0xeb, 0x72, 0xa0,
0x07, 0x74, 0x19, 0x72, 0x87, 0xa8, 0xba, 0x14,
0x75, 0xfe, 0x0f, 0x48, 0x0a, 0xaf, 0x31, 0x05,
0x9f, 0x4b, 0xcc, 0x18, 0x91, 0x38, 0x23, 0xde,
0xde, 0xf9, 0xaf, 0x15, 0xa3, 0x75, 0x09, 0x9e,
0x9d, 0x3d, 0x21, 0x1e, 0xc4, 0x26, 0x35, 0x1e,
0xb1, 0x12, 0x8e, 0x96, 0x4d, 0xfc, 0xbf, 0xde,
0x8f, 0x3c, 0x5d, 0x3b, 0x69, 0xe9, 0x75, 0xbd,
0xcf, 0xed, 0x1b, 0x79, 0xea, 0x0a, 0x3d, 0x02,
0x1c, 0xf8, 0x24, 0x56, 0xc6, 0x4d, 0x18, 0x04,
0x69, 0x3b, 0x1c, 0x52, 0x51, 0xda, 0x88, 0x2f,
0x42, 0x6b, 0x93, 0x8f, 0x42, 0xef, 0x83, 0xc9,
0x0c, 0xbb, 0xb4, 0x2f, 0x87, 0x2c, 0x8c, 0x3b,
0x42, 0x1a, 0x19, 0x87, 0xa2, 0x23, 0xee, 0x9b,
0xe9, 0xc6, 0x84, 0xb4, 0xa1, 0x54, 0x4c, 0xe9,
0x10, 0x8e, 0xa2, 0x0d, 0x6f, 0xe1, 0xef, 0xfa,
0x52, 0xda, 0x86, 0xe2, 0x7f, 0xaa, 0x8d, 0x76,
0xc1, 0x59, 0x6e, 0x87, 0x6b, 0x41, 0xde, 0x5c,
0x60, 0xd8, 0x06, 0xb0, 0xc3, 0x0e, 0xcc, 0x5e,
0x54, 0x14, 0x90, 0x9f, 0x48, 0xef, 0x6e, 0x5c,
0x61, 0x6e, 0x99, 0xee, 0x30, 0xc2, 0x9e, 0xf0,
0x30, 0x52, 0xb9, 0xe4, 0x3b, 0x16, 0x58, 0xf2,
0x77, 0x4a, 0xc6, 0x43, 0x1f, 0x6c, 0x09, 0x7d,
0xbb, 0x30, 0x6b, 0x72, 0x76, 0xfe, 0xd6, 0x87,
0x27, 0xfd, 0x4d, 0x7f, 0x59, 0x81, 0xb5, 0xe5,
0x4e, 0xc0, 0x27, 0x20, 0x02, 0x26, 0xda, 0x95,
0x67, 0xf6, 0xcc, 0x45, 0xc5, 0x24, 0x59, 0xa8,
0x46, 0x8f, 0xb5, 0x08, 0x09, 0x1b, 0xf3, 0xd8,
0x52, 0xd3, 0x83, 0x65, 0x20, 0x5f, 0xa6, 0x1c,
0xb6, 0x47, 0xe9, 0x57, 0xf9, 0x8e, 0x2b, 0xd5,
0xdc, 0xe5, 0xf8, 0x1f, 0x57, 0x25, 0x31, 0x3a,
0x92, 0x7a, 0xee, 0x0b, 0x6a, 0x66, 0xa1, 0x51,
0xe9, 0x03, 0xb0, 0x13, 0x4d, 0x87, 0x0b, 0x58,
0xac, 0xd6, 0xf4, 0xa6, 0x1a, 0x73, 0xa7, 0xa5,
0xe8, 0x35, 0x86, 0xc9, 0x87, 0x47, 0x8e, 0xc8,
0x07, 0x11, 0xaa, 0x1c, 0x27, 0x99, 0x48, 0xe0,
0xd3, 0x9e, 0x41, 0x7c, 0xc6, 0x0f, 0x76, 0x0a,
0x45, 0x6a, 0xb1, 0xcc, 0x62, 0x8b, 0xad, 0x4d,
0x5f, 0xbd, 0x59, 0x6b, 0x38, 0x35, 0x6a, 0xef,
0xa5, 0x63, 0x75, 0x57, 0x73, 0x12, 0x0c, 0x3c,
0xf2, 0x84, 0x5b, 0x95, 0x92, 0xb5, 0x33, 0x38,
0x13, 0x2a, 0x8e, 0x74, 0x6a, 0x91, 0x4f, 0xf9,
0x23, 0x99, 0x18, 0x19, 0x12, 0xf9, 0x5b, 0x17,
0xac, 0xb4, 0x5f, 0x6e, 0xe2, 0x67, 0xc5, 0x0f,
0x56, 0x99, 0x93, 0x36, 0x82, 0x45, 0x83, 0x29,
0x29, 0xf0, 0x0c, 0xfe, 0x2d, 0x57, 0x10, 0x06,
0xcb, 0xff, 0xff, 0xff, 0xcb, 0x11, 0x65, 0xce,
0x05, 0xaf, 0xb5, 0xf2, 0x33, 0x3c, 0xb0, 0xa5,
0xc6, 0x78, 0xb9, 0x9f, 0xa5, 0xea, 0xab, 0xd3,
0xfd, 0x8d, 0xda, 0x16, 0x2c, 0x85, 0x21, 0x33,
0xc1, 0x5c, 0x24, 0xaa, 0x63, 0x76, 0xfd, 0x69,
0x7e, 0xd9, 0x71, 0x75, 0x2f, 0x79, 0xa0, 0x33,
0x76, 0x5d, 0xbf, 0x59, 0x79, 0xf3, 0xd1, 0x04,
0xd7, 0x34, 0xc8, 0x78, 0x67, 0x9b, 0x59, 0xaf,
0x0d, 0x90, 0x08, 0x93, 0x44, 0x81, 0xdb, 0x48,
0x3b, 0xb0, 0x1d, 0x13, 0xe6, 0xd4, 0xcd, 0xc2,
0x17, 0x5c, 0x74, 0x97, 0x2a, 0x2f, 0x2e, 0x4d,
0xbd, 0xec, 0x91, 0x83, 0xec, 0x79, 0x33, 0x7f,
0x1e, 0xb6, 0x14, 0xa3, 0x86, 0x0d, 0x02, 0x03,
0x01, 0x00, 0x01, 0x02, 0x82, 0x02, 0x01, 0x00,
0x9b, 0xce, 0x94, 0x5a, 0xfd, 0x01, 0x4f, 0xbe,
0x5c, 0xb4, 0xdb, 0xa8, 0x35, 0x15, 0x55, 0xe8,
0x19, 0xb8, 0xdc, 0x3a, 0x26, 0xf1, 0x49, 0x7f,
0xc8, 0x9e, 0xf5, 0x4e, 0xc9, 0xee, 0x95, 0x1f,
0x4d, 0x7a, 0x07, 0x5b, 0x95, 0x54, 0x7e, 0xf4,
0xf0, 0xf5, 0x5c, 0x6e, 0xa5, 0x0d, 0x00, 0x75,
0x8b, 0x15, 0xd6, 0x9b, 0x91, 0x65, 0xf7, 0x69,
0xb9, 0x44, 0x8a, 0x49, 0xf9, 0xf8, 0x01, 0x13,
0xc7, 0xe0, 0x4b, 0xc4, 0xcc, 0xfc, 0x73, 0x59,
0x59, 0xc2, 0x83, 0x97, 0xff, 0xfd, 0x55, 0x8c,
0x11, 0xc3, 0x60, 0xa4, 0x9c, 0xed, 0x7f, 0x6f,
0x7f, 0x34, 0xe4, 0x2f, 0x7a, 0xf6, 0x26, 0x06,
0xd2, 0x2b, 0x30, 0xf7, 0x59, 0x69, 0x39, 0x85,
0x7d, 0x02, 0x57, 0xeb, 0x9f, 0x80, 0x10, 0xab,
0x6f, 0x7a, 0x0d, 0x5a, 0x87, 0xd2, 0xdc, 0xb8,
0xb4, 0xb8, 0xe3, 0x18, 0x47, 0x14, 0x8e, 0x05,
0x6a, 0x0d, 0xc0, 0x3a, 0xc7, 0x35, 0x64, 0xcc,
0xd8, 0xad, 0x8e, 0x53, 0xde, 0x9b, 0x66, 0x6c,
0xda, 0xd8, 0xbc, 0x04, 0x65, 0x11, 0x7d, 0x24,
0xb3, 0x6c, 0x1d, 0xd3, 0x56, 0x8e, 0x3f, 0x17,
0xc3, 0xc7, 0xc0, 0xf3, 0x4a, 0xaa, 0x9a, 0x45,
0x64, 0xd7, 0xaf, 0x18, 0x59, 0x18, 0x8e, 0xb7,
0xd7, 0xc2, 0x44, 0x8b, 0x5b, 0x85, 0x06, 0x5f,
0xde, 0x22, 0xaf, 0xd2, 0x93, 0x12, 0x03, 0x3e,
0xff, 0xa4, 0xaf, 0xc4, 0xdf, 0xe4, 0xfe, 0x41,
0x96, 0xa7, 0x87, 0xb4, 0x1d, 0x44, 0x00, 0xb1,
0x84, 0x42, 0x4a, 0x89, 0x25, 0x4e, 0x53, 0x02,
0xc9, 0xed, 0xeb, 0x40, 0xd3, 0x77, 0xf6, 0x58,
0x8e, 0x47, 0x88, 0x4c, 0xce, 0xf2, 0x20, 0x88,
0xfc, 0x33, 0x1f, 0xf4, 0xb2, 0x8a, 0x01, 0xc1,
0x19, 0x7d, 0xd6, 0x42, 0xff, 0x17, 0x5b, 0x7f,
0x31, 0xa6, 0xde, 0xee, 0xc7, 0x4c, 0x35, 0x53,
0x4d, 0x7e, 0x47, 0xb4, 0x2e, 0x67, 0xb5, 0x12,
0xf0, 0x81, 0xfc, 0x0c, 0xef, 0xd5, 0xbc, 0x6e,
0x9e, 0x80, 0x0f, 0xdf, 0x11, 0xff, 0x16, 0x1f,
0x47, 0x7a, 0x5d, 0x4e, 0x78, 0x34, 0xdf, 0x25,
0x7d, 0x52, 0x8a, 0x56, 0xdc, 0x34, 0xec, 0xf8,
0xd7, 0xa0, 0x51, 0x42, 0x37, 0x27, 0x14, 0x73,
0xf1, 0x14, 0xf6, 0x51, 0x97, 0x5b, 0xca, 0x4a,
0x1a, 0xcd, 0x32, 0x60, 0xeb, 0x97, 0x42, 0x94,
0x93, 0xc7, 0x1a, 0x1b, 0x08, 0x66, 0xcb, 0xa1,
0xe0, 0xa7, 0xc2, 0xab, 0x13, 0xba, 0x2b, 0x5f,
0xe6, 0x37, 0x7f, 0x62, 0x42, 0x78, 0xd0, 0x61,
0xdd, 0x8c, 0xe6, 0x6f, 0x9f, 0x27, 0x8a, 0xe5,
0x82, 0x3b, 0xca, 0xd8, 0xa6, 0x4a, 0x46, 0xa9,
0x3a, 0x99, 0x1c, 0x9e, 0xd9, 0xea, 0x82, 0x22,
0x61, 0x3e, 0xb1, 0x68, 0x8a, 0x49, 0x6c, 0x55,
0x5b, 0x91, 0xe0, 0xe8, 0x83, 0x08, 0x1e, 0x1d,
0x9d, 0x17, 0xe1, 0x75, 0x9b, 0xf0, 0xb8, 0x2b,
0x49, 0x60, 0xdf, 0x7b, 0xe4, 0x9d, 0x8e, 0x96,
0x3c, 0xa9, 0x7e, 0x45, 0xd1, 0x3f, 0x48, 0x8e,
0x61, 0xc1, 0x60, 0xf1, 0xf4, 0x4a, 0xd1, 0x1b,
0x2b, 0x79, 0xc6, 0xe0, 0x3d, 0x51, 0x3a, 0xfe,
0x9c, 0x6b, 0xb7, 0xcc, 0xe5, 0xe2, 0xbf, 0xa6,
0xee, 0x7d, 0xe0, 0xdb, 0x47, 0xa0, 0x17, 0x00,
0x17, 0xe3, 0x45, 0xd6, 0xfb, 0xdd, 0xc0, 0x1a,
0x8f, 0x87, 0x94, 0x2a, 0x40, 0xd7, 0xce, 0xb6,
0xaf, 0x78, 0xb4, 0xfa, 0x11, 0xe9, 0xf8, 0x4d,
0x6a, 0xb3, 0x62, 0xa2, 0xdf, 0x33, 0x28, 0x3d,
0x07, 0x18, 0x70, 0x66, 0x89, 0x73, 0x5d, 0xdb,
0x6c, 0x39, 0xc1, 0x43, 0x3b, 0x55, 0xdd, 0x39,
0xd1, 0x98, 0x0f, 0xb5, 0x0a, 0x12, 0xde, 0x60,
0xaf, 0x1d, 0x1d, 0x3b, 0xe4, 0x7e, 0x1f, 0x0a,
0x3b, 0x89, 0x70, 0xcc, 0xc8, 0x2d, 0xc0, 0x41,
0x02, 0x82, 0x01, 0x01, 0x00, 0xf9, 0xf7, 0xed,
0x9d, 0x43, 0xf6, 0xfe, 0xbf, 0x9e, 0x35, 0xe7,
0x89, 0xa9, 0xaa, 0xca, 0x25, 0xa6, 0xd1, 0xc9,
0x58, 0x89, 0xc4, 0xaf, 0x39, 0xf6, 0xf3, 0x9f,
0xa5, 0xdd, 0x35, 0x78, 0xac, 0x83, 0x1a, 0xb0,
0xae, 0x5a, 0x5b, 0x93, 0xb9, 0x3c, 0xb9, 0xe4,
0xdc, 0x1a, 0x1f, 0xd7, 0x39, 0x38, 0x2b, 0x7d,
0x9a, 0xae, 0x17, 0x9a, 0x0f, 0x83, 0xc9, 0xf8,
0x36, 0x72, 0x3a, 0x04, 0x47, 0xec, 0x5d, 0xbf,
0x40, 0xdb, 0xf8, 0xe8, 0x4c, 0xbf, 0x4a, 0x62,
0x35, 0xa9, 0x95, 0xfd, 0x0f, 0xcb, 0x1f, 0xb1,
0xf6, 0xcf, 0xa1, 0xa6, 0x28, 0xdb, 0xc4, 0x44,
0xe2, 0x6e, 0xd7, 0x83, 0x34, 0xf7, 0x0c, 0x23,
0x75, 0x9d, 0x3c, 0x22, 0xf7, 0xd8, 0x68, 0xe7,
0xd6, 0x3a, 0x9e, 0xe0, 0x5b, 0x79, 0x4d, 0x6a,
0x44, 0x1c, 0x03, 0x9f, 0x90, 0x5e, 0xde, 0x02,
0x74, 0x5c, 0x8d, 0x22, 0x2e, 0xe4, 0x00, 0x9c,
0xba, 0xcd, 0x72, 0x21, 0xdc, 0xab, 0x49, 0x50,
0xb6, 0xbd, 0x1a, 0x05, 0x27, 0x80, 0x3d, 0x43,
0xb5, 0x83, 0xcd, 0x0a, 0xbc, 0x54, 0xd6, 0x89,
0x2f, 0xae, 0x4e, 0x9e, 0xa8, 0xd6, 0xb3, 0xea,
0x44, 0xdd, 0x33, 0xee, 0x5f, 0x1f, 0x8f, 0xe8,
0x20, 0x7f, 0x3d, 0xf7, 0xb4, 0x00, 0x45, 0x86,
0x46, 0x9b, 0x89, 0x13, 0xc7, 0x1a, 0x6f, 0x87,
0x85, 0x62, 0xcd, 0x55, 0xab, 0x41, 0x3c, 0xc6,
0xb4, 0xd5, 0x3a, 0xce, 0x00, 0xd6, 0x6b, 0x2b,
0xa4, 0x56, 0x34, 0x30, 0xc9, 0x63, 0x67, 0x84,
0x45, 0xec, 0x22, 0x40, 0x8c, 0x73, 0xf5, 0x67,
0xa8, 0x8b, 0xc6, 0x81, 0xe9, 0xb6, 0x6f, 0x0e,
0x91, 0x5a, 0xf7, 0x69, 0x25, 0xf3, 0x70, 0x8a,
0x79, 0x0c, 0x48, 0xf7, 0x2a, 0x00, 0x9f, 0xc4,
0x22, 0x2f, 0x16, 0x28, 0x42, 0xcd, 0x37, 0xfe,
0x05, 0x81, 0x50, 0x4e, 0x5d, 0x02, 0x82, 0x01,
0x01, 0x00, 0xea, 0xad, 0xae, 0x40, 0x3b, 0xb2,
0x5f, 0x69, 0x24, 0x72, 0x5e, 0xfa, 0x3f, 0xd5,
0x9f, 0xac, 0x69, 0xea, 0x2c, 0x47, 0x26, 0xa4,
0x64, 0x70, 0x03, 0xac, 0xb8, 0x7f, 0x57, 0xa8,
0x94, 0xe1, 0xe9, 0xc6, 0x25, 0xea, 0x1d, 0x3d,
0x32, 0x88, 0xce, 0x46, 0xd5, 0xd1, 0x94, 0xeb,
0xc5, 0x9c, 0xd9, 0x61, 0xaf, 0x66, 0xd8, 0xf0,
0xec, 0xfe, 0x77, 0x38, 0xdd, 0xd3, 0x13, 0x05,
0x19, 0x18, 0xee, 0xdd, 0x65, 0xef, 0x80, 0xd4,
0x3f, 0x9c, 0x6f, 0xb3, 0xfc, 0xc2, 0x34, 0xd1,
0x34, 0xe3, 0x5e, 0xd5, 0x78, 0xad, 0x4b, 0x1d,
0x6e, 0x73, 0xbb, 0x62, 0x6b, 0x29, 0x1b, 0x72,
0xbc, 0x8f, 0xd2, 0x90, 0x40, 0x61, 0xf1, 0x58,
0x38, 0x91, 0x75, 0xc5, 0xbd, 0xc7, 0x5a, 0x08,
0x21, 0xdc, 0x3c, 0xca, 0xa3, 0xb6, 0x0f, 0x28,
0x27, 0xfe, 0x10, 0x6d, 0x0e, 0x23, 0x12, 0x9a,
0x0c, 0x9e, 0xf2, 0x34, 0xf9, 0x1c, 0xec, 0x1b,
0x30, 0x2a, 0xda, 0x47, 0x93, 0xe9, 0xe6, 0xee,
0x0b, 0xa7, 0xed, 0xb9, 0x66, 0xd8, 0x2d, 0xfd,
0x93, 0x55, 0x5b, 0xfd, 0x97, 0xa7, 0x2c, 0x2a,
0xe0, 0xaa, 0xd4, 0x46, 0xeb, 0xda, 0xdf, 0x2b,
0x4b, 0x68, 0xee, 0x42, 0xb7, 0xcc, 0x60, 0x0c,
0x21, 0x2e, 0xd9, 0xb7, 0xd8, 0x3d, 0x89, 0xd3,
0x2c, 0xed, 0xce, 0xc4, 0xbe, 0x9a, 0x53, 0xf8,
0x5d, 0x8f, 0xfd, 0x66, 0xe0, 0x84, 0xf5, 0x60,
0xa9, 0x6b, 0x26, 0x0f, 0x9e, 0x50, 0x77, 0xf9,
0x1c, 0x9c, 0x8e, 0x98, 0xeb, 0xe1, 0x02, 0xb6,
0x68, 0x0b, 0x37, 0xfb, 0xf5, 0x80, 0x1d, 0x2f,
0xfd, 0x98, 0x93, 0x07, 0x87, 0x81, 0x59, 0x70,
0x23, 0xc3, 0xdf, 0xe2, 0xd6, 0x86, 0xbb, 0x3e,
0xdf, 0xfd, 0xc3, 0xbf, 0xfa, 0x76, 0x72, 0x63,
0x5b, 0xfc, 0x62, 0x45, 0x0e, 0xbd, 0xc5, 0x8f,
0xbb, 0x71, 0x02, 0x82, 0x01, 0x00, 0x74, 0x2a,
0xf5, 0x81, 0xa5, 0xc9, 0x4e, 0xe0, 0xcc, 0x6c,
0xee, 0xba, 0xba, 0x60, 0x05, 0xeb, 0xf3, 0x98,
0x01, 0x43, 0xa5, 0x5b, 0x03, 0xb8, 0x23, 0x7d,
0x5b, 0x0f, 0x61, 0x3b, 0x6d, 0x66, 0x76, 0xd3,
0x5b, 0x92, 0xdb, 0xa9, 0x3d, 0x80, 0xd3, 0xa8,
0xec, 0xa4, 0x21, 0x7b, 0xf4, 0xb0, 0xc1, 0xda,
0xec, 0x57, 0x8b, 0x5a, 0xaa, 0x9d, 0x55, 0x38,
0xf2, 0xa2, 0x92, 0xf9, 0x45, 0x6e, 0x0b, 0x7a,
0x11, 0xdc, 0xd9, 0x9d, 0xd6, 0x8f, 0x7c, 0x42,
0xdc, 0x5b, 0x66, 0x01, 0xaf, 0x86, 0xbc, 0x76,
0x71, 0x65, 0x6b, 0x5f, 0x0b, 0x72, 0x67, 0x97,
0xd2, 0x0f, 0x8d, 0x45, 0x98, 0xd3, 0x6f, 0x90,
0x73, 0x96, 0x40, 0x49, 0x67, 0x52, 0xd9, 0x7e,
0xff, 0x67, 0x3e, 0xfd, 0x00, 0xf5, 0x61, 0xed,
0x49, 0x5a, 0x77, 0xce, 0x73, 0x44, 0x4b, 0xe2,
0x4f, 0x2f, 0xb6, 0xa7, 0x5c, 0x60, 0x80, 0x53,
0x8c, 0x82, 0xff, 0xe1, 0x6f, 0xbd, 0x36, 0xd9,
0x2e, 0xaa, 0x8e, 0x3d, 0x5e, 0x71, 0xda, 0x16,
0x1e, 0xb6, 0x67, 0x97, 0x4d, 0xca, 0xf2, 0x7e,
0x75, 0x68, 0xf4, 0x4f, 0xd3, 0x4a, 0x51, 0xe5,
0x71, 0x15, 0x29, 0xdb, 0xed, 0x86, 0xc5, 0x8b,
0x42, 0x6c, 0x7f, 0xd5, 0xd3, 0x9d, 0x12, 0x97,
0x3c, 0xec, 0xe9, 0x71, 0x8e, 0x00, 0x74, 0xd7,
0xaa, 0x1a, 0xa2, 0x2d, 0x1d, 0x08, 0x26, 0x9c,
0x51, 0x18, 0x4f, 0x14, 0x32, 0x12, 0x8f, 0x93,
0x64, 0xc7, 0xcd, 0xcc, 0x19, 0x74, 0x2e, 0x3f,
0x38, 0x68, 0xaa, 0x71, 0xcc, 0x9f, 0xb9, 0x70,
0x2e, 0x09, 0x55, 0x54, 0x1e, 0xa1, 0xf7, 0xc7,
0xaa, 0xf4, 0x80, 0x5b, 0x04, 0xc1, 0xbf, 0x5d,
0xe8, 0xec, 0x92, 0x7a, 0x02, 0x6b, 0xc1, 0xb8,
0x7e, 0x15, 0x08, 0xde, 0xfa, 0x3c, 0xf9, 0x54,
0x71, 0x38, 0x2b, 0xbd, 0x9f, 0x7d, 0x02, 0x82,
0x01, 0x01, 0x00, 0x81, 0x90, 0xe8, 0x6e, 0xb0,
0x46, 0xd7, 0xe4, 0x7d, 0xe9, 0xe3, 0x44, 0x38,
0xf0, 0x21, 0x9b, 0x18, 0x52, 0xe0, 0xa5, 0x5b,
0xd1, 0x51, 0x5e, 0x82, 0xb8, 0xde, 0x97, 0xf7,
0xf6, 0xac, 0x54, 0x5a, 0x34, 0x3b, 0x04, 0x99,
0xa6, 0x0a, 0xfb, 0x7b, 0x1f, 0xa2, 0xb7, 0x76,
0x88, 0x01, 0x6f, 0x8a, 0x99, 0x23, 0x35, 0x1e,
0x3b, 0x4e, 0x2d, 0x63, 0xf7, 0x72, 0x89, 0x31,
0xac, 0x13, 0xe2, 0x2f, 0x26, 0xef, 0x3b, 0x9f,
0x1e, 0x10, 0x0c, 0xb7, 0xa3, 0x60, 0xbe, 0x7c,
0x58, 0xb0, 0xe1, 0x83, 0x9f, 0x4a, 0x64, 0x2a,
0xdf, 0x91, 0xf6, 0xb5, 0x93, 0x2d, 0xe4, 0xe1,
0x31, 0xa4, 0xa7, 0xa7, 0x32, 0x5b, 0x49, 0x77,
0xed, 0x24, 0x36, 0x33, 0x16, 0xbc, 0xa3, 0x8e,
0xb2, 0x84, 0xb7, 0x4a, 0x9c, 0xfa, 0x6b, 0xee,
0xcc, 0x55, 0xe0, 0x30, 0x83, 0x75, 0x55, 0xa9,
0xd4, 0x81, 0x79, 0x53, 0xf2, 0x29, 0x43, 0x6d,
0x9b, 0xc9, 0x29, 0x2f, 0xa0, 0x6b, 0x2a, 0xad,
0x83, 0xe9, 0xcd, 0x8a, 0x33, 0x5d, 0x73, 0xa7,
0x58, 0xa3, 0xfa, 0x71, 0xb2, 0x7e, 0x03, 0x1f,
0x20, 0x81, 0x2f, 0xef, 0xc9, 0x44, 0x38, 0x70,
0x14, 0x40, 0x2b, 0x2b, 0xb8, 0x8c, 0x2f, 0x7b,
0x2b, 0xd7, 0x3a, 0x3d, 0x9c, 0x01, 0xf8, 0x5f,
0xda, 0xc6, 0xa8, 0x79, 0x0b, 0x28, 0xcc, 0x9d,
0xe5, 0xb7, 0x0a, 0x63, 0x76, 0x64, 0x29, 0x24,
0x2c, 0x7c, 0xfd, 0x1a, 0x63, 0x6f, 0x1d, 0xb0,
0x4f, 0x4a, 0x1b, 0xa9, 0xa3, 0x06, 0x40, 0x11,
0xb6, 0x51, 0x95, 0x38, 0x10, 0x94, 0xc7, 0x69,
0xd5, 0xf0, 0x26, 0x47, 0xae, 0xd5, 0x82, 0x75,
0xb5, 0xb3, 0x19, 0x56, 0xc7, 0xaf, 0x77, 0x6d,
0x73, 0xd6, 0x49, 0x0d, 0xc5, 0x35, 0x6c, 0x25,
0xd5, 0x73, 0x98, 0xd1, 0x4c, 0x9d, 0x49, 0xeb,
0x04, 0x63, 0x11, 0x02, 0x82, 0x01, 0x00, 0x61,
0x57, 0xc5, 0x3e, 0x84, 0x46, 0x16, 0x4c, 0x3c,
0x5e, 0x10, 0x3b, 0x16, 0x76, 0x5a, 0xa2, 0xba,
0xdb, 0x92, 0xc5, 0x56, 0xc9, 0xe9, 0xd9, 0x91,
0x16, 0x80, 0xca, 0xdd, 0xc4, 0x1b, 0xe3, 0xc1,
0x15, 0xf9, 0xbd, 0x81, 0x9f, 0xe4, 0xfa, 0xd5,
0xd2, 0x69, 0xbc, 0x0c, 0x23, 0x4d, 0x61, 0xc0,
0xf7, 0x82, 0x5a, 0xd3, 0xa2, 0x63, 0xad, 0xb7,
0xab, 0x6b, 0x26, 0xb5, 0x5c, 0xa5, 0xf0, 0xba,
0x7d, 0x7b, 0xd0, 0xbc, 0xb3, 0xe4, 0x4f, 0xc1,
0x94, 0xee, 0xe6, 0xd9, 0x4c, 0xad, 0x04, 0x1b,
0x95, 0x27, 0x88, 0x5e, 0xe6, 0xf8, 0x56, 0x5d,
0x67, 0x47, 0xe8, 0x20, 0x02, 0x77, 0x9c, 0xf5,
0x7b, 0x03, 0x35, 0xaa, 0xbb, 0x6e, 0x23, 0xa1,
0x88, 0x71, 0x10, 0x1d, 0x6f, 0x88, 0x5c, 0xa8,
0xbf, 0x93, 0x94, 0xfd, 0x63, 0x97, 0x9a, 0x9b,
0x2c, 0x23, 0x9e, 0x9c, 0x71, 0x49, 0x6c, 0x1d,
0x92, 0x78, 0x14, 0x3d, 0x64, 0xb8, 0xd4, 0x35,
0xe8, 0x88, 0x65, 0x42, 0x83, 0x6b, 0xff, 0x5d,
0x0d, 0x81, 0xa4, 0xd4, 0x38, 0xc2, 0x44, 0x8f,
0x78, 0x4c, 0x88, 0x8b, 0xca, 0x41, 0x34, 0x8b,
0x6d, 0xe7, 0x36, 0x02, 0x75, 0x68, 0xc2, 0x79,
0x45, 0xc3, 0x0c, 0x81, 0x4f, 0xe1, 0xd6, 0x54,
0x5f, 0xe3, 0x6e, 0x70, 0x60, 0x52, 0xbf, 0x23,
0x61, 0x1e, 0xa0, 0x81, 0xd4, 0xcc, 0x96, 0xd5,
0x5d, 0x10, 0x07, 0x62, 0xf7, 0xb6, 0x17, 0x02,
0xcc, 0x80, 0x3d, 0x9a, 0x07, 0x58, 0xc0, 0xc3,
0x9c, 0x7d, 0x6a, 0x69, 0x80, 0x51, 0xb6, 0xdf,
0xc3, 0xc6, 0x1f, 0xc7, 0x29, 0x23, 0x25, 0x53,
0xb0, 0x09, 0x7d, 0x33, 0x8c, 0xf6, 0x9b, 0x80,
0x9c, 0x19, 0xe6, 0x57, 0x41, 0x8e, 0x15, 0xc0,
0x0d, 0xdf, 0xbf, 0xbf, 0xe0, 0x33, 0x7f, 0x36,
0x30, 0xc6, 0x4f, 0x55, 0x95, 0x31, 0x93};
static const uint8_t RSA6144[] = {
0x30, 0x82, 0x0d, 0xc2, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x0d, 0xac, 0x30, 0x82, 0x0d, 0xa8, 0x02, 0x01,
0x00, 0x02, 0x82, 0x03, 0x01, 0x00, 0xbb, 0x67,
0x41, 0x02, 0xb9, 0xea, 0x1b, 0x1b, 0xd6, 0x7e,
0xaf, 0x4b, 0x13, 0xff, 0x77, 0x8a, 0x70, 0x6e,
0xb6, 0xe9, 0xdf, 0xfa, 0x75, 0x42, 0x7e, 0x58,
0x69, 0x3b, 0x6c, 0x35, 0x4e, 0xcc, 0xad, 0x21,
0x7a, 0x4b, 0x8b, 0x8e, 0xb7, 0x42, 0xcc, 0xad,
0x69, 0xdf, 0xb9, 0x3b, 0x68, 0xd2, 0x68, 0x93,
0x92, 0x13, 0x0a, 0x52, 0x0e, 0x55, 0xbf, 0xe8,
0xce, 0x28, 0x78, 0x1e, 0x53, 0x78, 0x9f, 0x4b,
0xe9, 0x9e, 0x3f, 0xa8, 0x76, 0x00, 0xa8, 0x01,
0x31, 0x6a, 0x69, 0xd7, 0x95, 0x43, 0x9c, 0x7e,
0xe0, 0x7e, 0x9b, 0xdc, 0x67, 0xe1, 0x49, 0xe1,
0xaa, 0xf6, 0x69, 0xb1, 0xbb, 0xeb, 0xa5, 0x60,
0x65, 0xd4, 0x3f, 0xd0, 0x13, 0x3a, 0x81, 0x79,
0xc5, 0xe0, 0xbd, 0x60, 0xd5, 0x15, 0x85, 0x61,
0x01, 0xd5, 0xc9, 0x3b, 0xd7, 0x3a, 0xb0, 0x7f,
0x84, 0xa6, 0x64, 0xe2, 0x78, 0x2b, 0x03, 0x47,
0x79, 0x96, 0x80, 0x40, 0x43, 0x12, 0xe5, 0xb2,
0x28, 0x14, 0xf6, 0xc9, 0x5a, 0xd6, 0x49, 0x39,
0xc5, 0x8a, 0xaf, 0x85, 0x12, 0x9c, 0xd1, 0xc9,
0x8f, 0x28, 0x0e, 0x5d, 0x5a, 0x9d, 0xa4, 0x6a,
0xe5, 0x41, 0x06, 0xdb, 0x84, 0xb8, 0xb5, 0xb7,
0x1d, 0x3c, 0xb6, 0x19, 0xa0, 0xf3, 0xfb, 0x1f,
0xc8, 0xea, 0x5e, 0x2a, 0x8b, 0x21, 0x6a, 0x46,
0xa9, 0xe9, 0x00, 0x0a, 0x2d, 0x9b, 0x26, 0xb8,
0x6b, 0x27, 0x61, 0x71, 0xf8, 0x40, 0xb0, 0xe5,
0xe4, 0xcd, 0x9a, 0x4d, 0x7c, 0x3b, 0xf2, 0x3b,
0x2c, 0xe4, 0xf2, 0xb5, 0x8a, 0x3f, 0xae, 0xfd,
0xc6, 0x49, 0x8d, 0x41, 0xfd, 0xc7, 0xcb, 0x01,
0xda, 0xda, 0x96, 0xc9, 0x5b, 0x3f, 0xde, 0x69,
0x01, 0x07, 0x25, 0x98, 0x54, 0x7a, 0x7f, 0x13,
0xc4, 0xcf, 0x28, 0x4d, 0x0a, 0xba, 0x8c, 0x17,
0xc5, 0xfa, 0x37, 0xcd, 0xb5, 0xd6, 0x50, 0x53,
0xaa, 0x23, 0xa5, 0x4d, 0xf7, 0x18, 0x7d, 0xd0,
0x79, 0x26, 0x3a, 0x65, 0x44, 0x3f, 0x98, 0xbd,
0x50, 0x39, 0xb8, 0xde, 0x81, 0x3a, 0x88, 0x05,
0x99, 0x6a, 0x7e, 0x45, 0x66, 0xca, 0x07, 0x7d,
0xe8, 0xfc, 0x44, 0x04, 0x87, 0x63, 0x7f, 0x4e,
0x0f, 0xc7, 0x40, 0xaf, 0xed, 0x7c, 0xae, 0x53,
0x55, 0xbf, 0xc3, 0xba, 0xd3, 0xa4, 0xd8, 0x9c,
0x14, 0xc9, 0x61, 0xd7, 0xe1, 0x47, 0x8c, 0xbf,
0xdd, 0x08, 0x16, 0x69, 0x20, 0x7a, 0x86, 0x88,
0xc4, 0x60, 0xff, 0xdf, 0x57, 0x68, 0x10, 0x53,
0xbc, 0x39, 0xf1, 0xb0, 0xd9, 0xf1, 0xb0, 0x66,
0x60, 0x70, 0x91, 0x57, 0x67, 0x43, 0x09, 0x44,
0x3e, 0x6d, 0x10, 0xff, 0x6c, 0x9c, 0xda, 0x89,
0xaf, 0xd8, 0x2d, 0xd1, 0xce, 0x68, 0xb7, 0xca,
0x86, 0xf9, 0xc6, 0x55, 0x6f, 0xf5, 0x8b, 0xdf,
0x4a, 0x7e, 0x79, 0xce, 0xb3, 0xec, 0xe4, 0x74,
0x48, 0x8b, 0x89, 0x95, 0x4d, 0xf0, 0x49, 0x46,
0x99, 0xfb, 0x3d, 0x01, 0x8e, 0xe6, 0x9e, 0x86,
0x06, 0xf2, 0xc1, 0x59, 0xf9, 0x27, 0xa8, 0xa8,
0x00, 0x62, 0x21, 0x40, 0xce, 0x68, 0x37, 0x93,
0x91, 0xdb, 0xd9, 0x93, 0xb0, 0xc3, 0xad, 0xf1,
0x90, 0xb9, 0x2b, 0xd2, 0x8a, 0xdf, 0x2e, 0x1d,
0xaa, 0x70, 0xde, 0x97, 0xc8, 0x20, 0x98, 0x75,
0x22, 0x21, 0xb3, 0xaa, 0x47, 0x53, 0x74, 0xce,
0x0c, 0x5a, 0x5d, 0x4f, 0xf3, 0xea, 0xe1, 0x27,
0xca, 0xa4, 0x4d, 0x69, 0xd2, 0xcb, 0x3d, 0xd6,
0x7a, 0x3b, 0xfc, 0x82, 0x66, 0x9a, 0x68, 0xf1,
0x9e, 0x2f, 0xef, 0xd1, 0x14, 0x35, 0xe0, 0x53,
0xc2, 0x81, 0xf3, 0x4e, 0xc7, 0xa1, 0x90, 0x52,
0xcc, 0xf3, 0xa7, 0x4f, 0xa1, 0xf8, 0x55, 0x43,
0x48, 0x3c, 0x4e, 0xec, 0xa9, 0x3c, 0x06, 0x40,
0x27, 0xfe, 0xcf, 0xac, 0xed, 0x12, 0x35, 0x17,
0x45, 0x1b, 0x22, 0x19, 0xf0, 0x6d, 0x0a, 0x30,
0x35, 0x11, 0x11, 0x10, 0x2d, 0x2c, 0x59, 0xcf,
0xeb, 0x4c, 0x8a, 0xe2, 0x7e, 0xc3, 0x3b, 0x95,
0xb5, 0x10, 0x6b, 0x1d, 0x00, 0xdc, 0x81, 0x59,
0x72, 0x16, 0x6c, 0x32, 0x81, 0x20, 0x2f, 0xba,
0x2d, 0xbd, 0x51, 0x3a, 0x80, 0x54, 0x63, 0x75,
0xf5, 0x49, 0x9f, 0x27, 0xe2, 0x2a, 0x19, 0xe4,
0x85, 0x0b, 0x5d, 0x74, 0x58, 0x35, 0x5c, 0x29,
0x96, 0x93, 0xf3, 0x8f, 0x3a, 0x08, 0x2c, 0xb1,
0x6d, 0xb2, 0x3a, 0xdb, 0xfd, 0x57, 0x3a, 0x32,
0x15, 0x4b, 0x5e, 0x95, 0x26, 0x58, 0xc1, 0xd3,
0x4c, 0xd6, 0xe6, 0x34, 0xef, 0x18, 0x1c, 0xa3,
0x75, 0xf8, 0x79, 0xce, 0x7b, 0xd4, 0x60, 0xa4,
0xa4, 0xdb, 0xf5, 0xdb, 0xc0, 0x14, 0x76, 0x83,
0x04, 0xb1, 0x45, 0x18, 0x70, 0x0d, 0xc0, 0x69,
0x6f, 0xa1, 0xe0, 0x01, 0xc0, 0xf3, 0x34, 0xb4,
0x57, 0xb7, 0x0f, 0xaf, 0x2d, 0x4e, 0xab, 0x17,
0xd6, 0x4e, 0x31, 0xc3, 0x69, 0x33, 0xf3, 0x55,
0xe0, 0x98, 0x0a, 0x25, 0x9a, 0x2c, 0xb1, 0xa9,
0x1e, 0x3b, 0xcf, 0xd8, 0xd1, 0xb7, 0x2d, 0x14,
0x75, 0xc3, 0xa5, 0xab, 0x45, 0xd7, 0xbb, 0x13,
0x69, 0x2d, 0x12, 0xc6, 0x73, 0xca, 0x2c, 0xd2,
0xe6, 0x3a, 0x8e, 0x4f, 0x01, 0x67, 0x73, 0x8a,
0x54, 0xb9, 0x0e, 0xda, 0x72, 0x69, 0xa9, 0xde,
0x26, 0xb6, 0x6c, 0x2d, 0x81, 0x3f, 0x69, 0xfb,
0xee, 0xd0, 0x30, 0xb4, 0x50, 0x6e, 0x8c, 0x4d,
0x78, 0x8b, 0x37, 0xdb, 0xd0, 0xa0, 0xe1, 0x32,
0xea, 0x5d, 0x72, 0xd5, 0x16, 0x39, 0xde, 0x60,
0xe3, 0x47, 0x14, 0xfe, 0xfc, 0x4a, 0xfc, 0x7e,
0x40, 0x63, 0xbf, 0xc5, 0x3a, 0xc6, 0x9a, 0x17,
0xf6, 0x8b, 0xca, 0xd8, 0x32, 0x21, 0x59, 0xb2,
0xa4, 0xff, 0x3b, 0x15, 0x47, 0x4f, 0x02, 0x03,
0x01, 0x00, 0x01, 0x02, 0x82, 0x03, 0x00, 0x7e,
0xeb, 0x4a, 0x23, 0x2f, 0x88, 0x76, 0x7d, 0x9f,
0x02, 0x43, 0x73, 0xe4, 0x82, 0x53, 0x12, 0x86,
0x5c, 0xe5, 0x32, 0x75, 0xc7, 0xa9, 0x5c, 0xb4,
0x36, 0xea, 0x66, 0x1d, 0x3d, 0xe9, 0x35, 0x43,
0x57, 0xf5, 0xfc, 0x6d, 0xf2, 0xe4, 0xf8, 0xaf,
0xa8, 0x0e, 0x99, 0x3f, 0x59, 0x15, 0xff, 0xd2,
0x65, 0x87, 0x3b, 0xaf, 0xf4, 0xac, 0xd2, 0xb4,
0x5b, 0x56, 0x2c, 0x20, 0x55, 0xe1, 0x90, 0x42,
0xca, 0x65, 0xd9, 0x10, 0x21, 0xe6, 0x71, 0x41,
0x57, 0x35, 0x81, 0x6d, 0x57, 0x5d, 0x36, 0xe2,
0x29, 0x27, 0x9f, 0x77, 0xad, 0x89, 0x09, 0x12,
0x41, 0x6c, 0xc8, 0xe0, 0x02, 0x48, 0x54, 0x2a,
0xb7, 0xa3, 0x9f, 0x60, 0xec, 0x69, 0xe9, 0x68,
0xc0, 0xf1, 0x1b, 0xe9, 0x06, 0x48, 0xa9, 0xff,
0xa0, 0x18, 0x5f, 0x12, 0x9f, 0x9d, 0x7f, 0x99,
0x03, 0x73, 0xf2, 0x41, 0x47, 0x03, 0xbd, 0x95,
0xc5, 0xf5, 0x79, 0xd1, 0x38, 0x34, 0x74, 0xfa,
0xed, 0x72, 0xa9, 0xe8, 0x0d, 0xac, 0xa0, 0x8e,
0x0d, 0x3b, 0x55, 0x56, 0xd4, 0x18, 0x2b, 0xef,
0x04, 0xc4, 0x18, 0x8b, 0xc9, 0xfb, 0xd1, 0xe2,
0x05, 0xa7, 0x68, 0x27, 0xdd, 0xca, 0x00, 0x52,
0xc9, 0x46, 0x5a, 0xd4, 0xb5, 0x7c, 0xc5, 0x60,
0x61, 0x41, 0x70, 0x41, 0x00, 0x2d, 0x24, 0x1f,
0x56, 0xe6, 0x41, 0xf0, 0x0d, 0xf4, 0x9f, 0x2c,
0x55, 0x1f, 0xf5, 0x16, 0xd0, 0xda, 0x21, 0xed,
0xec, 0x74, 0xce, 0x2e, 0x5f, 0xa5, 0xf0, 0xef,
0x77, 0xd6, 0x4a, 0xe4, 0x79, 0xc0, 0xbc, 0xaa,
0xa6, 0x22, 0x81, 0xb3, 0xd2, 0x6a, 0xae, 0xc2,
0x35, 0x6a, 0x64, 0x3a, 0x54, 0xfa, 0xa0, 0xc1,
0xdf, 0x79, 0x9b, 0xbe, 0x81, 0x71, 0x4d, 0x58,
0xfd, 0x29, 0x80, 0x67, 0x39, 0xee, 0x37, 0x33,
0x23, 0xf2, 0xa8, 0x28, 0xdc, 0xff, 0xf6, 0xba,
0x86, 0x3f, 0x27, 0x4f, 0x10, 0x03, 0x76, 0x29,
0xd7, 0x64, 0x05, 0x58, 0xed, 0x36, 0x90, 0x9f,
0xc0, 0x2f, 0x32, 0x38, 0x9b, 0x31, 0x08, 0x54,
0x10, 0xfe, 0xbb, 0x19, 0xf3, 0xa4, 0xce, 0xd4,
0xce, 0x18, 0x59, 0xa9, 0x33, 0x2c, 0x02, 0x5d,
0xb8, 0x9f, 0x85, 0x01, 0xb1, 0x64, 0x74, 0xd9,
0x97, 0x84, 0xee, 0x8f, 0xff, 0xda, 0xd0, 0xbd,
0x06, 0xd0, 0x29, 0x27, 0x43, 0xce, 0xc5, 0xe7,
0x74, 0x15, 0x9d, 0x21, 0x98, 0x67, 0x2f, 0xb4,
0x27, 0xb2, 0x60, 0x43, 0x4a, 0x9e, 0x66, 0xd3,
0x0f, 0xf2, 0xdd, 0x87, 0x6b, 0x8f, 0xdf, 0x58,
0xe9, 0xad, 0x0c, 0xef, 0xd2, 0x33, 0x14, 0x3a,
0x95, 0x66, 0x75, 0xf5, 0x5a, 0x17, 0xd4, 0x0f,
0x49, 0xca, 0xb6, 0xed, 0x29, 0x37, 0xd2, 0xc2,
0x0e, 0xbe, 0xe5, 0x30, 0xc6, 0xb2, 0x41, 0xa9,
0x4e, 0x3b, 0xa4, 0x76, 0x98, 0x60, 0x4f, 0xb7,
0x9f, 0x4e, 0xe4, 0x88, 0x60, 0x3d, 0x40, 0x66,
0x65, 0xe6, 0xee, 0xf2, 0x02, 0x87, 0x40, 0xdb,
0x14, 0x4c, 0x08, 0x1c, 0xae, 0xa9, 0x4f, 0xc3,
0xed, 0xcd, 0xa8, 0xd3, 0x63, 0x3a, 0x61, 0x6c,
0x1b, 0xf2, 0x98, 0xfc, 0x32, 0x2d, 0x4f, 0x14,
0x31, 0x8c, 0x4d, 0x3d, 0x8d, 0x4b, 0x25, 0xfb,
0xe8, 0x97, 0x88, 0x72, 0x72, 0x47, 0x45, 0x44,
0x06, 0x17, 0x8c, 0xda, 0x3e, 0x99, 0xc6, 0xd7,
0xaa, 0x38, 0x21, 0x2c, 0x74, 0x4e, 0xfd, 0x53,
0x92, 0x88, 0x66, 0x99, 0x66, 0xce, 0xa9, 0x2d,
0x2a, 0x90, 0x27, 0xcb, 0x96, 0x1f, 0x9b, 0xe9,
0x53, 0x77, 0x1a, 0x3b, 0x33, 0x98, 0x43, 0x21,
0x35, 0x74, 0x8b, 0xc1, 0x18, 0xf4, 0x25, 0x4b,
0x4a, 0x79, 0x00, 0x29, 0x59, 0x99, 0x89, 0x55,
0xe6, 0x9d, 0xd4, 0x3a, 0x93, 0xa0, 0xd7, 0x0c,
0x29, 0x5d, 0xc7, 0xaa, 0x4e, 0x3f, 0xde, 0x28,
0x9a, 0x10, 0xd5, 0x6f, 0x46, 0xb4, 0xc7, 0x7f,
0x10, 0x61, 0xa1, 0xcf, 0x3f, 0x01, 0x5a, 0xfb,
0x4d, 0x2f, 0x21, 0x9b, 0x03, 0xa6, 0x77, 0x3c,
0x8c, 0x1e, 0x53, 0xd2, 0x60, 0x6d, 0xc6, 0x60,
0x0e, 0x7d, 0x78, 0x94, 0xaf, 0xa2, 0xc7, 0xd2,
0x7d, 0x01, 0xda, 0x4a, 0xc4, 0x65, 0x8d, 0xa3,
0x62, 0x1b, 0x74, 0xfe, 0x6a, 0x07, 0x0a, 0xaa,
0x29, 0xed, 0xfe, 0x24, 0x38, 0xfa, 0x0e, 0x6c,
0x63, 0x8d, 0xd3, 0x5e, 0x36, 0xc4, 0x0d, 0xf7,
0x9d, 0x74, 0x2a, 0x2b, 0x8a, 0x36, 0x7a, 0x0f,
0xb8, 0x39, 0xa0, 0x3d, 0x94, 0xd8, 0x8d, 0xf7,
0x69, 0xdb, 0xe4, 0x4e, 0x20, 0x3f, 0x89, 0xc2,
0x5c, 0x24, 0x81, 0xe4, 0xc7, 0x99, 0x6d, 0x25,
0xa1, 0x0d, 0xe5, 0x06, 0x64, 0xec, 0x41, 0xe0,
0x59, 0x18, 0x72, 0xf8, 0x8f, 0xfa, 0xb6, 0x05,
0xa2, 0x4c, 0x48, 0x80, 0x19, 0xe3, 0xd2, 0x56,
0x06, 0xe6, 0x73, 0xda, 0xb8, 0x51, 0xba, 0xb5,
0xed, 0x85, 0x04, 0x76, 0x9f, 0x6e, 0x34, 0x1b,
0xa8, 0x5a, 0xec, 0xfb, 0x80, 0xd8, 0xf4, 0xc4,
0xfc, 0xa5, 0x5c, 0x33, 0xe0, 0x6f, 0x05, 0x79,
0x04, 0x65, 0x3f, 0xbb, 0xe6, 0x3b, 0xee, 0x69,
0xf9, 0xfa, 0x8b, 0x7d, 0x8a, 0x69, 0xaa, 0x67,
0x26, 0xcb, 0x83, 0xfc, 0xa6, 0x96, 0x6c, 0x83,
0xd9, 0x13, 0xe4, 0x7c, 0x9c, 0x01, 0x3d, 0x8d,
0xa3, 0xb8, 0xbd, 0xa1, 0x19, 0x4e, 0x46, 0x74,
0xc9, 0x80, 0xc6, 0x3c, 0x96, 0xfe, 0xa0, 0x01,
0x66, 0x3b, 0x48, 0xdb, 0x16, 0xc6, 0xe6, 0x72,
0x1b, 0x93, 0x3f, 0xc2, 0x2a, 0x7f, 0x56, 0x06,
0x73, 0x69, 0x69, 0x07, 0x06, 0xf3, 0xef, 0xb6,
0xad, 0x94, 0xbd, 0x92, 0x8f, 0x78, 0x5c, 0x9c,
0xbd, 0x39, 0x7b, 0x4f, 0xdb, 0xad, 0x56, 0x8c,
0x72, 0x85, 0x0a, 0x2e, 0xed, 0xa7, 0xa9, 0x02,
0x82, 0x01, 0x81, 0x00, 0xf9, 0x8b, 0xb2, 0x1c,
0x57, 0x75, 0x7e, 0x5b, 0x53, 0x5f, 0x60, 0x40,
0x7b, 0x39, 0x8b, 0xf8, 0x4e, 0x59, 0x5d, 0x3b,
0xd5, 0xa1, 0x0b, 0xe1, 0x2b, 0x11, 0x1f, 0x44,
0x5b, 0x17, 0x80, 0x5e, 0x98, 0x0e, 0x89, 0xe9,
0xf5, 0x0d, 0x59, 0xe1, 0xcc, 0x88, 0x58, 0x83,
0x64, 0x03, 0x97, 0x06, 0x31, 0xd4, 0x44, 0x89,
0xf2, 0x96, 0xa8, 0x1d, 0xf3, 0x47, 0x93, 0x0d,
0x1a, 0xc7, 0x6a, 0x55, 0xfc, 0x3e, 0x2c, 0x6f,
0x67, 0x97, 0x3e, 0x73, 0x46, 0x78, 0x02, 0x09,
0xae, 0x36, 0xaa, 0x02, 0x65, 0xf8, 0xe3, 0xe9,
0xc8, 0xe7, 0xbe, 0xfa, 0xc1, 0xcf, 0xd3, 0xd1,
0x4b, 0x85, 0x18, 0x15, 0x68, 0x5e, 0x3c, 0x34,
0xeb, 0x3a, 0x40, 0x2e, 0x98, 0xe1, 0x09, 0xcc,
0x65, 0xa5, 0xfc, 0x3f, 0x4d, 0xaa, 0x1d, 0x89,
0x35, 0x49, 0x93, 0xb5, 0xb5, 0x4b, 0xe4, 0x48,
0x71, 0x80, 0x85, 0xc3, 0x5a, 0x99, 0x2b, 0xfd,
0x20, 0xdc, 0x47, 0xb6, 0x9a, 0xd1, 0x03, 0x74,
0x2c, 0xff, 0x7c, 0x0a, 0x31, 0xfc, 0xbb, 0x30,
0x07, 0x28, 0xe5, 0x8b, 0x27, 0xe7, 0x91, 0x37,
0xe0, 0x84, 0xcf, 0xa3, 0xc4, 0x42, 0xb5, 0xc6,
0xae, 0x69, 0x3a, 0x7d, 0xfc, 0x38, 0x4f, 0xef,
0x02, 0xdb, 0x3e, 0x36, 0xf4, 0x97, 0xeb, 0x25,
0x6b, 0x0a, 0x3f, 0x7f, 0xd9, 0xd3, 0x20, 0xd2,
0xdd, 0x5b, 0x40, 0x99, 0xdf, 0xb4, 0x11, 0xbb,
0x26, 0xa6, 0x86, 0xf5, 0xaa, 0xe2, 0x13, 0x84,
0xb9, 0x6b, 0x64, 0xa0, 0x77, 0x88, 0xac, 0x3f,
0x27, 0x88, 0x9e, 0x1c, 0x26, 0x14, 0x8d, 0x82,
0xc6, 0x0f, 0x18, 0xda, 0xa6, 0x80, 0x63, 0x2a,
0x5b, 0x36, 0xcd, 0x19, 0xe9, 0xce, 0x5c, 0x0f,
0xd1, 0x19, 0xf4, 0x3b, 0x01, 0x03, 0xcc, 0x16,
0x05, 0xf1, 0x6e, 0x66, 0xea, 0xf4, 0xb6, 0x18,
0x10, 0x47, 0x3d, 0xc3, 0xe4, 0x78, 0x47, 0x60,
0xa7, 0xdc, 0xab, 0xb5, 0x69, 0x41, 0xa1, 0xfb,
0xe4, 0x36, 0xad, 0xe0, 0xad, 0xbf, 0x58, 0x70,
0xa2, 0x90, 0x51, 0x65, 0x64, 0xe5, 0xea, 0x0d,
0x9c, 0x43, 0x9e, 0x6d, 0xaf, 0xcd, 0x6f, 0x6b,
0x56, 0xd4, 0xfe, 0x57, 0x35, 0x70, 0x1f, 0xf2,
0x78, 0x92, 0x64, 0x5e, 0xb7, 0xd4, 0x31, 0x03,
0x28, 0x58, 0xd4, 0x89, 0xb5, 0x67, 0x45, 0x1b,
0x85, 0xa2, 0x97, 0x7c, 0xa7, 0xa2, 0xd6, 0x33,
0x14, 0x80, 0xaf, 0xe0, 0x10, 0x6b, 0xd1, 0x2c,
0xa1, 0x24, 0x38, 0xc7, 0x79, 0x26, 0x76, 0x55,
0x57, 0x95, 0x6f, 0xda, 0xfd, 0x45, 0x19, 0xfc,
0x71, 0x2f, 0x49, 0xdd, 0x0b, 0xd9, 0x4a, 0xbf,
0x53, 0x18, 0x48, 0xa4, 0x86, 0x9d, 0x81, 0x90,
0x27, 0xfb, 0xbf, 0xcb, 0xf7, 0x1a, 0xb3, 0x26,
0x88, 0x1d, 0x56, 0xcb, 0x55, 0x8b, 0x2e, 0xde,
0xb8, 0x1c, 0x0f, 0x33, 0x02, 0x82, 0x01, 0x81,
0x00, 0xc0, 0x40, 0x19, 0x23, 0x2f, 0xf3, 0x7e,
0x70, 0x1f, 0xca, 0xda, 0x2a, 0x46, 0xaa, 0xac,
0xe2, 0xcc, 0x85, 0x0d, 0x72, 0x8e, 0xc6, 0xe6,
0xed, 0xac, 0x12, 0xe9, 0x21, 0x3a, 0x89, 0x44,
0xf7, 0x8c, 0xd0, 0x15, 0x0c, 0xad, 0xdb, 0x80,
0xa6, 0x91, 0x76, 0x0b, 0x4a, 0xd6, 0xda, 0x71,
0x8c, 0x2d, 0x30, 0x16, 0x37, 0x0f, 0x02, 0x9e,
0xd9, 0xcb, 0xec, 0x64, 0x57, 0x8e, 0x48, 0x52,
0xae, 0xfc, 0xb3, 0x32, 0x85, 0x4f, 0xe2, 0xaa,
0x9a, 0x59, 0xfa, 0xbf, 0x2a, 0xd0, 0xdd, 0x00,
0x36, 0xeb, 0xc9, 0xec, 0x56, 0xb6, 0xa2, 0xb1,
0x9f, 0xe9, 0xac, 0x04, 0x5f, 0x1f, 0xe0, 0x7a,
0x4f, 0x07, 0x54, 0x5d, 0x53, 0x6b, 0x21, 0x7e,
0x57, 0x26, 0xf2, 0xd9, 0x0c, 0xb9, 0x15, 0xa7,
0x7b, 0x77, 0xe5, 0x5f, 0x13, 0xbd, 0xdb, 0x32,
0x1d, 0xfa, 0x6f, 0xa1, 0x67, 0x27, 0x51, 0x34,
0xd2, 0x24, 0x29, 0x8b, 0xf3, 0x13, 0x3a, 0xc3,
0x69, 0x04, 0x13, 0x65, 0x70, 0xc0, 0x52, 0xe0,
0xf5, 0x9a, 0x19, 0x87, 0x4a, 0xa6, 0x50, 0x00,
0x1c, 0x26, 0x47, 0x70, 0xd9, 0xd8, 0xba, 0x70,
0xa9, 0x6f, 0x5a, 0x32, 0x8f, 0x8d, 0xef, 0x9f,
0x6c, 0xc7, 0x71, 0xc2, 0xd1, 0x28, 0x57, 0x72,
0x69, 0xe2, 0x6e, 0x44, 0x9b, 0xb0, 0x33, 0xc6,
0x68, 0xca, 0x92, 0x05, 0xab, 0x8f, 0x2c, 0x94,
0x68, 0x28, 0x1e, 0x2e, 0xd6, 0xd3, 0xe0, 0x27,
0xed, 0x7f, 0x5f, 0xa2, 0x05, 0xc7, 0x80, 0xfa,
0x0c, 0x5b, 0xa0, 0x2b, 0x20, 0xec, 0xfa, 0xbe,
0x67, 0x06, 0x3a, 0xca, 0xb6, 0x90, 0x24, 0x5f,
0xb2, 0x3a, 0xbc, 0x62, 0xc6, 0x38, 0xca, 0xda,
0x3d, 0xd1, 0x5c, 0x33, 0xaf, 0xe8, 0xb1, 0x3d,
0x3b, 0x7a, 0x50, 0x2b, 0x55, 0xa4, 0x50, 0x06,
0x5d, 0x29, 0x2a, 0xad, 0xe7, 0xf0, 0x35, 0xc7,
0xcd, 0x50, 0xa7, 0x80, 0x85, 0x5e, 0xfd, 0xac,
0xcc, 0x75, 0x8a, 0xff, 0xdd, 0x3e, 0x54, 0x50,
0x1e, 0x1f, 0x86, 0x31, 0xbe, 0xef, 0xf3, 0x3f,
0xce, 0x60, 0x8e, 0x0e, 0xe0, 0x32, 0x93, 0x57,
0xfe, 0x4b, 0xa2, 0xaf, 0x0b, 0x48, 0xf8, 0xb0,
0xc2, 0x53, 0x8f, 0x6e, 0x39, 0xe1, 0x82, 0x9a,
0x91, 0x21, 0xfd, 0x9a, 0x36, 0x95, 0x86, 0x4f,
0x5c, 0xbf, 0x08, 0x86, 0x76, 0x2e, 0x14, 0x66,
0xe3, 0x41, 0x96, 0xa4, 0xe1, 0x93, 0x89, 0xde,
0x7e, 0xd1, 0x71, 0xf4, 0x02, 0x51, 0x04, 0x34,
0xef, 0x71, 0x33, 0x09, 0x40, 0x98, 0x9a, 0x05,
0x7f, 0x65, 0xb5, 0x4b, 0x49, 0x78, 0xc5, 0xc5,
0x87, 0xd5, 0x5d, 0x67, 0xe2, 0x03, 0x8c, 0xa6,
0x90, 0xb2, 0x01, 0x2f, 0xb7, 0x95, 0x4a, 0x13,
0xea, 0x50, 0x3f, 0x22, 0x92, 0xfc, 0x32, 0x53,
0xfd, 0x50, 0xd7, 0x5e, 0x3e, 0x9e, 0x88, 0x57,
0x75, 0x02, 0x82, 0x01, 0x81, 0x00, 0x81, 0xbe,
0x69, 0xfa, 0x66, 0x56, 0x86, 0x3d, 0xc1, 0x59,
0x43, 0x58, 0x03, 0x39, 0x66, 0x56, 0xd1, 0x95,
0x90, 0xed, 0xfd, 0x22, 0x60, 0x64, 0xcf, 0xd9,
0x75, 0x22, 0x3b, 0x22, 0x3a, 0xf1, 0xf3, 0xa9,
0x0b, 0x77, 0x82, 0x9b, 0x50, 0x72, 0x1f, 0xbf,
0x7c, 0x15, 0xc4, 0x38, 0x41, 0x9b, 0x4c, 0xe9,
0x0a, 0x41, 0x96, 0xc9, 0x51, 0xdb, 0x50, 0x93,
0x94, 0x17, 0x2a, 0x27, 0x28, 0x58, 0x50, 0x6f,
0x9a, 0xf6, 0xc9, 0x2b, 0x4f, 0xa2, 0xeb, 0xae,
0x95, 0x90, 0xa6, 0xed, 0x70, 0xf3, 0x12, 0x45,
0x97, 0x6a, 0x03, 0xb4, 0xca, 0x0c, 0xe2, 0x1b,
0xc6, 0x0b, 0x79, 0x72, 0x57, 0x95, 0x39, 0xd0,
0x55, 0x09, 0x46, 0x8b, 0xe0, 0xb6, 0xd9, 0x71,
0x97, 0x80, 0x98, 0x10, 0xf6, 0xd7, 0x8a, 0xef,
0xb9, 0xaf, 0x8e, 0xef, 0x14, 0x47, 0x53, 0x5d,
0x83, 0xf1, 0x4e, 0x61, 0xfe, 0x2a, 0x15, 0xbe,
0xb1, 0xaa, 0x48, 0x1d, 0x7f, 0x83, 0xa7, 0x76,
0xa8, 0x8f, 0x0c, 0x9e, 0x40, 0xc5, 0xa4, 0x3b,
0xbc, 0xaf, 0x39, 0xe9, 0xbf, 0x7e, 0xdc, 0x5e,
0x7f, 0x98, 0x47, 0xb9, 0x85, 0xa3, 0xa5, 0xf4,
0xf1, 0x41, 0xbd, 0x88, 0xa4, 0x8a, 0xc0, 0x4a,
0x1e, 0xf5, 0x2b, 0xcd, 0x05, 0xc9, 0xd8, 0xdd,
0xeb, 0xba, 0x66, 0xae, 0xcb, 0x59, 0x13, 0xcd,
0xbb, 0xb1, 0x26, 0xb9, 0xbd, 0x1a, 0xc3, 0xbe,
0x81, 0xc1, 0x86, 0x54, 0xea, 0xb2, 0x6c, 0x08,
0x63, 0x11, 0x8c, 0xbe, 0x13, 0x71, 0x82, 0xf4,
0xa2, 0x69, 0xab, 0x8a, 0x52, 0x7a, 0x5c, 0x2a,
0x2f, 0x71, 0x20, 0xbc, 0xd4, 0xb5, 0x4a, 0x00,
0x52, 0x8e, 0xc1, 0x21, 0xfa, 0xfd, 0x50, 0x1c,
0xa4, 0xac, 0xec, 0x90, 0xcb, 0xf4, 0xa9, 0x90,
0x69, 0xd9, 0xc1, 0x79, 0x47, 0x67, 0x67, 0x1d,
0x98, 0x57, 0x66, 0x8f, 0x43, 0xc3, 0xc7, 0xd3,
0xe9, 0x78, 0x8d, 0x8e, 0x24, 0x10, 0x8c, 0x0b,
0x3d, 0xc7, 0x13, 0x5e, 0x82, 0x84, 0xe0, 0x91,
0x2d, 0xd0, 0x52, 0x15, 0x2a, 0xdc, 0xc6, 0xda,
0xeb, 0x17, 0xec, 0x79, 0x13, 0xb3, 0xff, 0xc5,
0x95, 0xfa, 0x7f, 0x08, 0xfa, 0xbc, 0x28, 0xe2,
0x85, 0x19, 0xb2, 0x2a, 0x9a, 0xd8, 0xcc, 0x47,
0x1c, 0xbc, 0x81, 0x8b, 0xbd, 0xe5, 0x63, 0x55,
0xb0, 0x0e, 0xa1, 0x2a, 0x6a, 0x0c, 0xbb, 0xb3,
0xe4, 0x1e, 0x66, 0xb8, 0x89, 0xb8, 0xbb, 0x90,
0xf3, 0x0e, 0x7b, 0x31, 0xb3, 0xfb, 0xb2, 0x37,
0x97, 0x2a, 0xc4, 0x00, 0xc4, 0x49, 0x5d, 0x89,
0x41, 0xfb, 0x88, 0x75, 0x87, 0xb7, 0xcf, 0xe3,
0x48, 0x03, 0xb5, 0x96, 0x58, 0x9e, 0x82, 0x06,
0xfe, 0x48, 0x0f, 0x21, 0xcb, 0x14, 0xa7, 0x03,
0x50, 0xc5, 0xe5, 0xdb, 0x2b, 0x37, 0x48, 0xe0,
0xb6, 0x9b, 0xc1, 0xa9, 0x85, 0x15, 0x02, 0x82,
0x01, 0x80, 0x55, 0x04, 0x83, 0x99, 0x51, 0xfd,
0x46, 0x2e, 0xe3, 0x80, 0x5b, 0x96, 0x52, 0x85,
0xeb, 0xca, 0xa8, 0x53, 0x36, 0xad, 0x30, 0x82,
0xb9, 0x60, 0xe5, 0xb5, 0xbf, 0x2f, 0x18, 0xa9,
0xd7, 0xbb, 0xf9, 0xa3, 0x93, 0x8b, 0x75, 0xdf,
0x1a, 0x37, 0x8f, 0x20, 0x3a, 0xc2, 0x2f, 0xdd,
0x8e, 0x55, 0x45, 0x2e, 0x7c, 0xc4, 0x80, 0x78,
0xd2, 0x32, 0xd2, 0xc1, 0x89, 0x66, 0x46, 0xdf,
0xa8, 0xe1, 0x05, 0x93, 0x61, 0x86, 0x1e, 0xdb,
0xc8, 0x42, 0x56, 0x04, 0x53, 0x41, 0xe5, 0xf7,
0xb5, 0xbe, 0x93, 0xeb, 0x49, 0xfe, 0xd6, 0xe9,
0x7f, 0xcf, 0x8e, 0x10, 0xaa, 0x26, 0x3e, 0xfc,
0x90, 0x5a, 0x1e, 0x8d, 0xaa, 0x6f, 0xd7, 0x72,
0x8a, 0x62, 0x94, 0x30, 0xd4, 0xd7, 0x91, 0x8a,
0x07, 0xf4, 0xcc, 0x02, 0xbd, 0x57, 0x07, 0xa0,
0xc5, 0xbb, 0x08, 0x23, 0x11, 0xa7, 0x82, 0x75,
0xa0, 0xfc, 0x45, 0x4d, 0xb2, 0x3c, 0x1e, 0x86,
0xe0, 0x1f, 0xb2, 0xd3, 0xb9, 0x0a, 0x71, 0xa2,
0xb5, 0x25, 0x27, 0xae, 0x9e, 0x6b, 0xde, 0xbc,
0x86, 0x2f, 0xec, 0xa5, 0xaf, 0x3c, 0x47, 0x61,
0xbb, 0xac, 0xd2, 0x37, 0x7b, 0x20, 0x8c, 0xce,
0x29, 0x1c, 0x7b, 0xde, 0xcd, 0x1e, 0x9d, 0xce,
0x7e, 0x24, 0x61, 0x24, 0x0e, 0x67, 0x23, 0x36,
0xe2, 0x49, 0x39, 0x3b, 0xf6, 0x11, 0xf6, 0x50,
0xea, 0x98, 0x5d, 0x15, 0x6b, 0xf5, 0x48, 0xe1,
0x5a, 0x06, 0xe7, 0x4b, 0x2d, 0x65, 0x8c, 0xe2,
0x76, 0xb1, 0xbc, 0x5b, 0x4a, 0x77, 0x57, 0x15,
0x53, 0xda, 0x4f, 0xa0, 0xf4, 0x40, 0x63, 0xe2,
0x12, 0x07, 0xc9, 0x7d, 0xc1, 0xd8, 0x93, 0x08,
0xf2, 0x16, 0x60, 0x5d, 0x7b, 0xe6, 0x10, 0xeb,
0x40, 0x7e, 0xeb, 0x0a, 0x44, 0xff, 0xac, 0x98,
0x4f, 0x18, 0x27, 0xba, 0x5e, 0x09, 0xb1, 0xea,
0xb6, 0x9f, 0x0f, 0x49, 0xe3, 0xc6, 0x17, 0x49,
0xeb, 0x7e, 0xc7, 0x84, 0x5e, 0xbe, 0x42, 0x70,
0x1a, 0xb6, 0x17, 0x8e, 0xca, 0xb4, 0xfb, 0x7c,
0x00, 0xfd, 0x8d, 0x29, 0x85, 0x5e, 0x94, 0x3f,
0x20, 0xac, 0xae, 0x5a, 0x15, 0x3a, 0xd2, 0x5c,
0x58, 0x1e, 0xb7, 0xc1, 0x38, 0x27, 0x94, 0x98,
0xa3, 0x2e, 0x07, 0x70, 0x15, 0x20, 0x8a, 0x63,
0x48, 0xf9, 0x64, 0xe9, 0xaa, 0x3c, 0xdd, 0x07,
0xdc, 0xb0, 0x27, 0x33, 0x2d, 0x5b, 0x2c, 0x59,
0xcd, 0xf1, 0x1b, 0x42, 0x5f, 0x7c, 0x1e, 0xc3,
0xd3, 0x7d, 0x07, 0xfc, 0x5f, 0xdd, 0x17, 0x1f,
0x15, 0xcb, 0x4e, 0xf9, 0x2b, 0x80, 0x24, 0x4e,
0xa1, 0x99, 0xfe, 0x3b, 0x3e, 0x53, 0x6e, 0xea,
0x66, 0x46, 0x9a, 0xd1, 0x77, 0x7e, 0xa2, 0x20,
0x8e, 0x4a, 0x12, 0x8e, 0xb9, 0x05, 0x73, 0x4d,
0xf6, 0x62, 0x91, 0xbb, 0x8c, 0x4b, 0xf8, 0xe3,
0xa6, 0x79, 0x02, 0x82, 0x01, 0x80, 0x57, 0x3e,
0xb3, 0xc4, 0x22, 0x2f, 0xca, 0xfd, 0xcb, 0x14,
0x66, 0x86, 0xc2, 0x5c, 0x42, 0x71, 0xf9, 0x71,
0x2d, 0x62, 0x6f, 0x41, 0x42, 0x4a, 0x34, 0x9d,
0x9d, 0xae, 0x24, 0x69, 0x2a, 0x0f, 0x28, 0x30,
0xe0, 0x46, 0x44, 0x29, 0x6c, 0x5f, 0xec, 0xb1,
0xa6, 0x00, 0xf8, 0x64, 0xf8, 0x62, 0x08, 0x84,
0x1f, 0xe8, 0x89, 0x8b, 0x5d, 0x3f, 0x1d, 0xbf,
0x7f, 0x2b, 0x21, 0x10, 0x70, 0x5e, 0x70, 0xc7,
0x26, 0x64, 0x70, 0xfb, 0x17, 0x37, 0x9a, 0x94,
0xee, 0x37, 0xf2, 0x07, 0x4d, 0x56, 0xd9, 0x19,
0xc5, 0xa1, 0x7a, 0xcb, 0x98, 0x46, 0x27, 0x2d,
0xf9, 0x63, 0xa0, 0x12, 0x32, 0x76, 0x49, 0x46,
0xe5, 0x4f, 0xec, 0xcd, 0x17, 0xbf, 0x53, 0x8c,
0xd8, 0xf2, 0x69, 0xa4, 0x7f, 0x36, 0x98, 0x19,
0x36, 0x25, 0xf0, 0x25, 0xba, 0xe2, 0x31, 0xc7,
0xd3, 0x7a, 0xfb, 0xb1, 0x9b, 0x08, 0x58, 0xcd,
0xce, 0xb3, 0xa3, 0x11, 0x47, 0x53, 0x79, 0xe1,
0xe4, 0x04, 0xdc, 0x57, 0x2c, 0x89, 0xa4, 0xd5,
0x28, 0x46, 0x74, 0x94, 0x39, 0xda, 0xaf, 0x00,
0xb2, 0x70, 0xbc, 0xe3, 0x9d, 0x86, 0x10, 0xb3,
0x74, 0x83, 0x19, 0x49, 0x4c, 0x53, 0x14, 0x75,
0xc4, 0xa3, 0x42, 0x65, 0xeb, 0xdd, 0xf6, 0x3a,
0x0b, 0x84, 0xb4, 0x4f, 0x1c, 0x6b, 0x06, 0x1c,
0x74, 0xf9, 0xeb, 0x5f, 0x1d, 0x46, 0xea, 0xe3,
0x6b, 0x28, 0x62, 0xea, 0xc5, 0x79, 0x82, 0x41,
0x9b, 0x09, 0xf5, 0xc5, 0x07, 0x12, 0x17, 0x84,
0x75, 0x3f, 0xce, 0xd6, 0x66, 0x8c, 0x05, 0x52,
0xdc, 0x05, 0x08, 0xf8, 0xa2, 0xf4, 0x53, 0xc6,
0x71, 0xae, 0xe5, 0xe7, 0xde, 0x3f, 0xe7, 0x4f,
0x3b, 0xed, 0xb6, 0xfc, 0xcb, 0xf0, 0xb4, 0x1a,
0xb6, 0x6a, 0xd1, 0x56, 0xa7, 0x59, 0x86, 0xda,
0x12, 0xc7, 0xd8, 0xba, 0xa2, 0xf6, 0x5e, 0xf7,
0xd4, 0x28, 0x90, 0xa5, 0x26, 0xd0, 0x44, 0x01,
0x64, 0x21, 0x5b, 0xf8, 0xc7, 0x9c, 0x20, 0xea,
0x1f, 0xeb, 0x07, 0xe4, 0xc2, 0xed, 0x4c, 0x1b,
0x4b, 0x01, 0x9e, 0xb2, 0xd0, 0x61, 0xbb, 0x37,
0xfc, 0xbb, 0xe5, 0xc1, 0x9d, 0x10, 0x24, 0xe0,
0x9c, 0xe9, 0x33, 0x8f, 0x7b, 0xfb, 0x5a, 0xcb,
0x14, 0x08, 0x75, 0xa0, 0x3d, 0x3e, 0x14, 0x76,
0x0e, 0xf5, 0xd4, 0x42, 0x80, 0x5e, 0x78, 0xc8,
0x8d, 0xed, 0x55, 0x41, 0x7c, 0xfb, 0xcb, 0xf3,
0x1e, 0x73, 0x64, 0xab, 0x56, 0x8e, 0x78, 0xc1,
0x32, 0x35, 0x77, 0xa4, 0x4e, 0xe9, 0x67, 0x9a,
0xbd, 0x01, 0xc4, 0x47, 0xf6, 0x94, 0x14, 0x1c,
0x3b, 0x7a, 0x71, 0xe3, 0x03, 0xeb, 0x18, 0xd1,
0x60, 0x6f, 0x96, 0x81, 0xed, 0x4f, 0x43, 0x1d,
0x26, 0xae, 0xc3, 0xd2, 0x88, 0xc8, 0x8a, 0x2d,
0xa8, 0xce, 0xd6, 0x95, 0xd4, 0x33};
static const uint8_t MODP_768_P[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t MODP_768_G[] = {
0x02,
};
static const uint8_t MODP_1024_P[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t MODP_1024_G[] = {
0x02,
};
static const uint8_t MODP_1536_P[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t MODP_1536_G[] = {
0x02,
};
static const uint8_t MODP_2048_P[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t MODP_2048_G[] = {
0x02,
};
static const uint8_t MODP_3072_P[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b,
0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2,
0xec, 0x07, 0xa2, 0x8f, 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9,
0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7c,
0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10,
0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xaa, 0xc4, 0x2d, 0xad, 0x33, 0x17, 0x0d,
0x04, 0x50, 0x7a, 0x33, 0xa8, 0x55, 0x21, 0xab, 0xdf, 0x1c, 0xba, 0x64,
0xec, 0xfb, 0x85, 0x04, 0x58, 0xdb, 0xef, 0x0a, 0x8a, 0xea, 0x71, 0x57,
0x5d, 0x06, 0x0c, 0x7d, 0xb3, 0x97, 0x0f, 0x85, 0xa6, 0xe1, 0xe4, 0xc7,
0xab, 0xf5, 0xae, 0x8c, 0xdb, 0x09, 0x33, 0xd7, 0x1e, 0x8c, 0x94, 0xe0,
0x4a, 0x25, 0x61, 0x9d, 0xce, 0xe3, 0xd2, 0x26, 0x1a, 0xd2, 0xee, 0x6b,
0xf1, 0x2f, 0xfa, 0x06, 0xd9, 0x8a, 0x08, 0x64, 0xd8, 0x76, 0x02, 0x73,
0x3e, 0xc8, 0x6a, 0x64, 0x52, 0x1f, 0x2b, 0x18, 0x17, 0x7b, 0x20, 0x0c,
0xbb, 0xe1, 0x17, 0x57, 0x7a, 0x61, 0x5d, 0x6c, 0x77, 0x09, 0x88, 0xc0,
0xba, 0xd9, 0x46, 0xe2, 0x08, 0xe2, 0x4f, 0xa0, 0x74, 0xe5, 0xab, 0x31,
0x43, 0xdb, 0x5b, 0xfc, 0xe0, 0xfd, 0x10, 0x8e, 0x4b, 0x82, 0xd1, 0x20,
0xa9, 0x3a, 0xd2, 0xca, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const uint8_t MODP_3072_G[] = {
0x02,
};
static const uint8_t MODP_4096_P[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t MODP_4096_G[] = {
0x02,
};
static const uint8_t MODP_4096_P_INVALID[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x08, 0x08, 0x08};
namespace {
bool hmac_sa(
std::vector<uint8_t>& out,
sa_key key,
const std::vector<uint8_t>& in,
sa_digest_algorithm digest_algorithm) {
auto context = create_uninitialized_sa_crypto_mac_context();
if (context == nullptr) {
ERROR("create_uninitialized_sa_crypto_mac_context failed");
return false;
}
sa_mac_parameters_hmac parameters = {digest_algorithm};
if (sa_crypto_mac_init(context.get(), SA_MAC_ALGORITHM_HMAC, key, ¶meters) != SA_STATUS_OK) {
ERROR("sa_crypto_mac_init failed");
return false;
}
if (sa_crypto_mac_process(*context, in.data(), in.size()) != SA_STATUS_OK) {
ERROR("sa_crypto_mac_process failed");
return false;
}
size_t out_length = digest_length(digest_algorithm);
out.resize(out_length);
if (sa_crypto_mac_compute(out.data(), &out_length, *context) != SA_STATUS_OK) {
ERROR("sa_crypto_mac_compute failed");
return false;
}
return true;
}
bool decrypt_aes_ecb_sa(
std::vector<uint8_t>& out,
std::vector<uint8_t>& in,
sa_key key) {
auto context = create_uninitialized_sa_crypto_cipher_context();
if (context == nullptr) {
ERROR("create_uninitialized_sa_crypto_cipher_context failed");
return false;
}
if (sa_crypto_cipher_init(context.get(), SA_CIPHER_ALGORITHM_AES_ECB, SA_CIPHER_MODE_DECRYPT, key,
nullptr) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_init failed");
return false;
}
size_t length = in.size();
sa_buffer out_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {out.data(), out.size(), 0}}};
sa_buffer in_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {in.data(), in.size(), 0}}};
if (sa_crypto_cipher_process(&out_buffer, *context, &in_buffer, &length) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_process failed");
return false;
}
return true;
}
bool encrypt_aes_ecb_sa(
std::vector<uint8_t>& out,
std::vector<uint8_t>& in,
sa_key key) {
auto context = create_uninitialized_sa_crypto_cipher_context();
if (context == nullptr) {
ERROR("create_uninitialized_sa_crypto_cipher_context failed");
return false;
}
if (sa_crypto_cipher_init(context.get(), SA_CIPHER_ALGORITHM_AES_ECB, SA_CIPHER_MODE_ENCRYPT, key,
nullptr) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_init failed");
return false;
}
size_t length = in.size();
sa_buffer out_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {out.data(), out.size(), 0}}};
sa_buffer in_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {in.data(), in.size(), 0}}};
if (sa_crypto_cipher_process(&out_buffer, *context, &in_buffer, &length) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_process failed");
return false;
}
return true;
}
bool check_key_unwrap_rights(
const std::shared_ptr<sa_header>& parent_header,
const std::shared_ptr<sa_header>& child_header) {
if ((parent_header->rights.usage_flags & KEY_ONLY_MASK) != 0 ||
parent_header->rights.child_usage_flags == 0) {
uint64_t const disallowed = ~parent_header->rights.usage_flags & SA_USAGE_OUTPUT_PROTECTIONS_MASK;
if ((child_header->rights.usage_flags & ~disallowed) != 0)
return false;
} else {
uint64_t const disallowed = ~parent_header->rights.child_usage_flags & SA_KEY_USAGE_MASK;
if ((child_header->rights.usage_flags & ~disallowed) != 0)
return false;
}
return true;
}
bool key_check_hmac(
sa_key key,
const std::vector<uint8_t>& clear_key) {
auto input = random(AES_BLOCK_SIZE);
std::vector<uint8_t> sa3hmac(clear_key.size());
if (!hmac_sa(sa3hmac, key, input, SA_DIGEST_ALGORITHM_SHA256)) {
ERROR("hmac_sa failed");
return false;
}
std::vector<uint8_t> sslhmac(clear_key.size());
if (!hmac_openssl(sslhmac, clear_key, input, SA_DIGEST_ALGORITHM_SHA256)) {
ERROR("hmac_openssl failed");
return false;
}
if (sa3hmac != sslhmac) {
ERROR("hash values do not match");
return false;
}
return true;
}
bool key_check_decrypt_aes_ecb(
sa_key key,
const std::vector<uint8_t>& clear_key) {
auto clear = random(AES_BLOCK_SIZE);
auto encrypted = std::vector<uint8_t>(clear.size());
size_t const encrypted_length = clear.size();
if (!encrypt_aes_ecb_openssl(encrypted, clear, clear_key, false)) {
ERROR("encrypt_aes_ecb_openssl failed");
return false;
}
encrypted.resize(encrypted_length);
auto decrypted = std::vector<uint8_t>(encrypted.size());
if (!decrypt_aes_ecb_sa(decrypted, encrypted, key)) {
ERROR("decrypt_aes_ecb_sa failed");
return false;
}
if (clear != decrypted) {
ERROR("values do not match");
return false;
}
return true;
}
bool key_check_encrypt_aes_ecb(
sa_key key,
const std::vector<uint8_t>& clear_key) {
auto clear = random(AES_BLOCK_SIZE);
auto encrypted = std::vector<uint8_t>(clear.size());
if (!encrypt_aes_ecb_sa(encrypted, clear, key)) {
ERROR("encrypt_aes_ecb_sa failed");
return false;
}
auto decrypted = std::vector<uint8_t>(encrypted.size());
if (!decrypt_aes_ecb_openssl(decrypted, encrypted, clear_key, false)) {
ERROR("decrypt_aes_ecb_openssl failed");
return false;
}
if (clear != decrypted) {
ERROR("values do not match");
return false;
}
return true;
}
bool key_check_aes_ecb_unwrap(
sa_key key,
const std::vector<uint8_t>& clear_key) {
auto clear = random(AES_BLOCK_SIZE);
auto encrypted = std::vector<uint8_t>(clear.size());
if (!encrypt_aes_ecb_openssl(encrypted, clear, clear_key, false)) {
ERROR("encrypt_aes_ecb_openssl failed");
return false;
}
sa_rights rights;
sa_rights_set_allow_all(&rights);
auto unwrapped_key = create_uninitialized_sa_key();
if (unwrapped_key == nullptr) {
ERROR("create_uninitialized_sa_key failed");
return false;
}
if (sa_key_unwrap(unwrapped_key.get(), &rights, SA_KEY_TYPE_SYMMETRIC, nullptr, SA_CIPHER_ALGORITHM_AES_ECB,
nullptr, key, encrypted.data(), encrypted.size()) != SA_STATUS_OK) {
ERROR("sa_key_unwrap failed");
return false;
}
auto parent_header = key_header(key);
if (parent_header == nullptr) {
ERROR("Could not get key header");
return false;
}
auto unwrapped_key_header = key_header(*unwrapped_key);
if (unwrapped_key_header == nullptr) {
ERROR("Could not get key header");
return false;
}
check_key_unwrap_rights(parent_header, unwrapped_key_header);
if (SA_USAGE_BIT_TEST(unwrapped_key_header->rights.usage_flags, SA_USAGE_FLAG_ENCRYPT)) {
if (!key_check_encrypt_aes_ecb(*unwrapped_key, clear)) {
ERROR("key_check_encrypt_aes_ecb failed");
return false;
}
} else if (SA_USAGE_BIT_TEST(unwrapped_key_header->rights.usage_flags, SA_USAGE_FLAG_UNWRAP)) {
if (!key_check_aes_ecb_unwrap(*unwrapped_key, clear)) {
ERROR("key_check_aes_ecb_unwrap failed");
return false;
}
}
return true;
}
bool key_check_rsa_decrypt(sa_key key) {
auto clear = random(65);
std::vector<uint8_t> in(4096);
auto evp_pkey = std::shared_ptr<EVP_PKEY>(sa_get_public_key(key), EVP_PKEY_free);
if (evp_pkey == nullptr) {
ERROR("sa_get_public_key failed");
return false;
}
if (!encrypt_rsa_oaep_openssl(in, clear, evp_pkey, SA_DIGEST_ALGORITHM_SHA1, SA_DIGEST_ALGORITHM_SHA1,
{})) {
ERROR("encrypt_rsa_oaep_openssl failed");
return false;
}
auto cipher = create_uninitialized_sa_crypto_cipher_context();
if (cipher == nullptr) {
ERROR("create_uninitialized_sa_crypto_cipher_context failed");
return false;
}
sa_cipher_parameters_rsa_oaep parameters = {SA_DIGEST_ALGORITHM_SHA1, SA_DIGEST_ALGORITHM_SHA1, nullptr, 0};
if (sa_crypto_cipher_init(cipher.get(), SA_CIPHER_ALGORITHM_RSA_OAEP, SA_CIPHER_MODE_DECRYPT, key,
¶meters) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_init failed");
return false;
}
size_t length = in.size();
sa_buffer in_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {in.data(), in.size(), 0}}};
if (sa_crypto_cipher_process(nullptr, *cipher, &in_buffer, &length) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_process failed");
return false;
}
auto out = std::vector<uint8_t>(length);
sa_buffer out_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {out.data(), out.size(), 0}}};
length = in.size();
if (sa_crypto_cipher_process(&out_buffer, *cipher, &in_buffer, &length) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_process failed");
return false;
}
out.resize(length);
if (clear != out) {
ERROR("RSA decrypt failed");
return false;
}
return true;
}
bool key_check_rsa_oaep_unwrap(sa_key key) {
auto clear = random(AES_BLOCK_SIZE);
auto rsa = std::shared_ptr<EVP_PKEY>(sa_get_public_key(key), EVP_PKEY_free);
if (rsa == nullptr) {
ERROR("sa_get_public_key failed");
return false;
}
auto encrypted = std::vector<uint8_t>(EVP_PKEY_bits(rsa.get()) / 8);
if (!encrypt_rsa_oaep_openssl(encrypted, clear, rsa, SA_DIGEST_ALGORITHM_SHA1, SA_DIGEST_ALGORITHM_SHA1,
{})) {
ERROR("encrypt_rsa_oaep_openssl failed");
return false;
}
sa_rights rights;
sa_rights_set_allow_all(&rights);
auto unwrapped_key = create_uninitialized_sa_key();
if (unwrapped_key == nullptr) {
ERROR("create_uninitialized_sa_key failed");
return false;
}
sa_unwrap_parameters_rsa_oaep parameters = {SA_DIGEST_ALGORITHM_SHA1, SA_DIGEST_ALGORITHM_SHA1, nullptr, 0};
if (sa_key_unwrap(unwrapped_key.get(), &rights, SA_KEY_TYPE_SYMMETRIC, nullptr,
SA_CIPHER_ALGORITHM_RSA_OAEP, ¶meters, key, encrypted.data(),
encrypted.size()) != SA_STATUS_OK) {
ERROR("sa_key_unwrap failed");
return false;
}
auto parent_header = key_header(key);
if (parent_header == nullptr) {
ERROR("Could not get key header");
return false;
}
auto unwrapped_key_header = key_header(*unwrapped_key);
if (unwrapped_key_header == nullptr) {
ERROR("Could not get key header");
return false;
}
check_key_unwrap_rights(parent_header, unwrapped_key_header);
if (!key_check_sym(*unwrapped_key, clear)) {
ERROR("key_check_sym failed");
return false;
}
return true;
}
bool key_check_ec_elgamal_decrypt(sa_key key) {
auto header = key_header(key);
auto curve = header->type_parameters.curve;
size_t const key_size = ec_get_key_size(curve);
auto ec = std::shared_ptr<EVP_PKEY>(sa_get_public_key(key), EVP_PKEY_free);
if (ec == nullptr) {
ERROR("sa_get_public_key failed");
return false;
}
auto clear = random(key_size);
if (curve == SA_ELLIPTIC_CURVE_NIST_P521)
clear[0] &= 0x1;
std::vector<uint8_t> in;
if (!encrypt_ec_elgamal_openssl(in, clear, curve, ec)) {
ERROR("encrypt_ec_elgamal_openssl failed");
return false;
}
auto cipher = create_uninitialized_sa_crypto_cipher_context();
if (cipher == nullptr) {
ERROR("create_uninitialized_sa_crypto_cipher_context failed");
return false;
}
sa_status const status = sa_crypto_cipher_init(cipher.get(), SA_CIPHER_ALGORITHM_EC_ELGAMAL,
SA_CIPHER_MODE_DECRYPT, key, nullptr);
if (status == SA_STATUS_OPERATION_NOT_SUPPORTED)
return true;
if (status != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_init failed");
return false;
}
size_t length = in.size();
sa_buffer in_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {in.data(), in.size(), 0}}};
if (sa_crypto_cipher_process(nullptr, *cipher, &in_buffer, &length) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_process failed");
return false;
}
auto out = std::vector<uint8_t>(length);
sa_buffer out_buffer = {SA_BUFFER_TYPE_CLEAR, {.clear = {out.data(), out.size(), 0}}};
length = in.size();
if (sa_crypto_cipher_process(&out_buffer, *cipher, &in_buffer, &length) != SA_STATUS_OK) {
ERROR("sa_crypto_cipher_process failed");
return false;
}
out.resize(length);
if (clear != out) {
ERROR("EC decrypt failed");
return false;
}
return true;
}
bool key_check_ec_elgamal_unwrap(sa_key key) {
const int COUNTER_SIZE = 4;
auto header = key_header(key);
auto curve = header->type_parameters.curve;
auto clear_key = random(SYM_128_KEY_SIZE);
size_t const key_size = ec_get_key_size(curve);
std::vector<uint8_t> clear(key_size);
std::vector<uint8_t> in(128);
size_t const offset = ((key_size - COUNTER_SIZE - SYM_128_KEY_SIZE) / 8) * 8;
clear.assign(clear.size(), 0);
memcpy(clear.data() + offset, clear_key.data(), clear_key.size());
auto ec = std::shared_ptr<EVP_PKEY>(sa_get_public_key(key), EVP_PKEY_free);
if (ec == nullptr) {
ERROR("sa_get_public_key failed");
return false;
}
if (!encrypt_ec_elgamal_openssl(in, clear, curve, ec)) {
ERROR("encrypt_ec_elgamal_openssl failed");
return false;
}
sa_rights rights;
sa_rights_set_allow_all(&rights);
auto unwrapped_key = create_uninitialized_sa_key();
if (unwrapped_key == nullptr) {
ERROR("create_uninitialized_sa_key failed");
return false;
}
sa_unwrap_parameters_ec_elgamal params = {offset, clear_key.size()};
sa_status const status = sa_key_unwrap(unwrapped_key.get(), &rights, SA_KEY_TYPE_SYMMETRIC, nullptr,
SA_CIPHER_ALGORITHM_EC_ELGAMAL, ¶ms, key, in.data(), in.size());
if (status == SA_STATUS_OPERATION_NOT_SUPPORTED)
return true;
if (status != SA_STATUS_OK) {
ERROR("sa_key_unwrap failed");
return false;
}
auto parent_header = key_header(key);
if (parent_header == nullptr) {
ERROR("Could not get key header");
return false;
}
auto unwrapped_key_header = key_header(*unwrapped_key);
if (unwrapped_key_header == nullptr) {
ERROR("Could not get key header");
return false;
}
check_key_unwrap_rights(parent_header, unwrapped_key_header);
if (!key_check_sym(*unwrapped_key, clear_key)) {
ERROR("key_check_sym failed");
return false;
}
return true;
}
}
std::vector<uint8_t> sample_dh_p_768() {
return {MODP_768_P, MODP_768_P + sizeof(MODP_768_P)};
}
std::vector<uint8_t> sample_dh_g_768() {
return {MODP_768_G, MODP_768_G + sizeof(MODP_768_G)};
}
std::vector<uint8_t> sample_dh_p_1024() {
return {MODP_1024_P, MODP_1024_P + sizeof(MODP_1024_P)};
}
std::vector<uint8_t> sample_dh_g_1024() {
return {MODP_1024_G, MODP_1024_G + sizeof(MODP_1024_G)};
}
std::vector<uint8_t> sample_dh_p_1536() {
return {MODP_1536_P, MODP_1536_P + sizeof(MODP_1536_P)};
}
std::vector<uint8_t> sample_dh_g_1536() {
return {MODP_1536_G, MODP_1536_G + sizeof(MODP_1536_G)};
}
std::vector<uint8_t> sample_dh_p_2048() {
return {MODP_2048_P, MODP_2048_P + sizeof(MODP_2048_P)};
}
std::vector<uint8_t> sample_dh_g_2048() {
return {MODP_2048_G, MODP_2048_G + sizeof(MODP_2048_G)};
}
std::vector<uint8_t> sample_dh_p_3072() {
return {MODP_3072_P, MODP_3072_P + sizeof(MODP_3072_P)};
}
std::vector<uint8_t> sample_dh_g_3072() {
return {MODP_3072_G, MODP_3072_G + sizeof(MODP_3072_G)};
}
std::vector<uint8_t> sample_dh_p_4096() {
return {MODP_4096_P, MODP_4096_P + sizeof(MODP_4096_P)};
}
std::vector<uint8_t> sample_dh_g_4096() {
return {MODP_4096_G, MODP_4096_G + sizeof(MODP_4096_G)};
}
std::vector<uint8_t> sample_dh_invalid_p_4096() {
return {MODP_4096_P_INVALID, MODP_4096_P_INVALID + sizeof(MODP_4096_P_INVALID)};
}
std::vector<uint8_t> sample_rsa_1024_pkcs8() {
return {RSA1024, RSA1024 + sizeof(RSA1024)};
}
std::vector<uint8_t> sample_rsa_1024_pkcs8_e3() {
return {RSA1024_E3, RSA1024_E3 + sizeof(RSA1024_E3)};
}
std::vector<uint8_t> sample_rsa_2048_pkcs8() {
return {RSA2048, RSA2048 + sizeof(RSA2048)};
}
std::vector<uint8_t> sample_rsa_3072_pkcs8() {
return {RSA3072, RSA3072 + sizeof(RSA3072)};
}
std::vector<uint8_t> sample_rsa_4096_pkcs8() {
return {RSA4096, RSA4096 + sizeof(RSA4096)};
}
std::vector<uint8_t> sample_rsa_6144_pkcs8() {
return {RSA6144, RSA6144 + sizeof(RSA6144)};
}
std::tuple<std::vector<uint8_t>, std::vector<uint8_t>> get_dh_parameters(size_t key_size) {
switch (key_size) {
case DH_768_BYTE_LENGTH:
return {sample_dh_p_768(), sample_dh_g_768()};
case DH_1024_BYTE_LENGTH:
return {sample_dh_p_1024(), sample_dh_g_1024()};
case DH_1536_BYTE_LENGTH:
return {sample_dh_p_1536(), sample_dh_g_1536()};
case DH_2048_BYTE_LENGTH:
return {sample_dh_p_2048(), sample_dh_g_2048()};
case DH_3072_BYTE_LENGTH:
return {sample_dh_p_3072(), sample_dh_g_3072()};
case DH_4096_BYTE_LENGTH:
return {sample_dh_p_4096(), sample_dh_g_4096()};
default:
return {};
}
}
std::vector<uint8_t> get_rsa_private_key(size_t key_size) {
switch (key_size) {
case RSA_1024_BYTE_LENGTH:
return sample_rsa_1024_pkcs8();
case RSA_2048_BYTE_LENGTH:
return sample_rsa_2048_pkcs8();
case RSA_3072_BYTE_LENGTH:
return sample_rsa_3072_pkcs8();
case RSA_4096_BYTE_LENGTH:
return sample_rsa_4096_pkcs8();
default:
return {};
}
}
std::string iso8601(const uint64_t instant) {
static const char* ISO_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ";
auto time = static_cast<time_t>(instant);
struct tm ts {};
gmtime_r(&time, &ts);
char buf[256];
strftime(buf, sizeof(buf), ISO_TIME_FORMAT, &ts);
return {buf};
}
std::shared_ptr<sa_key> create_uninitialized_sa_key() {
return {new sa_key(INVALID_HANDLE),
[](const sa_key* p) {
if (p != nullptr) {
if (*p != INVALID_HANDLE) {
sa_key_release(*p);
}
delete p;
}
}};
}
std::shared_ptr<sa_crypto_cipher_context> create_uninitialized_sa_crypto_cipher_context() {
return {new sa_crypto_cipher_context(INVALID_HANDLE),
[](const sa_crypto_cipher_context* p) {
if (p != nullptr) {
if (*p != INVALID_HANDLE) {
sa_crypto_cipher_release(*p);
}
delete p;
}
}};
}
std::shared_ptr<sa_crypto_mac_context> create_uninitialized_sa_crypto_mac_context() {
return {new sa_crypto_mac_context(INVALID_HANDLE),
[](const sa_crypto_mac_context* p) {
if (p != nullptr) {
if (*p != INVALID_HANDLE) {
sa_crypto_mac_release(*p);
}
delete p;
}
}};
}
std::shared_ptr<sa_key> create_sa_key_symmetric(
const sa_rights* rights,
const std::vector<uint8_t>& clear_key) {
auto key = create_uninitialized_sa_key();
sa_import_parameters_symmetric params = {rights};
sa_status const status = sa_key_import(key.get(), SA_KEY_FORMAT_SYMMETRIC_BYTES, clear_key.data(),
clear_key.size(), ¶ms);
if (status == SA_STATUS_OPERATION_NOT_SUPPORTED) {
ERROR("Unsupported key type");
*key = UNSUPPORTED_KEY;
} else if (status != SA_STATUS_OK) {
ERROR("sa_key_import failed");
key = nullptr;
}
return key;
}
std::shared_ptr<sa_key> create_sa_key_rsa(
const sa_rights* rights,
const std::vector<uint8_t>& clear_key) {
auto key = create_uninitialized_sa_key();
sa_import_parameters_rsa_private_key_info params = {rights};
sa_status const status = sa_key_import(key.get(), SA_KEY_FORMAT_RSA_PRIVATE_KEY_INFO, clear_key.data(),
clear_key.size(), ¶ms);
if (status == SA_STATUS_OPERATION_NOT_SUPPORTED) {
ERROR("Unsupported key type");
*key = UNSUPPORTED_KEY;
} else if (status != SA_STATUS_OK) {
ERROR("sa_key_import failed");
key = nullptr;
}
return key;
}
std::shared_ptr<sa_key> create_sa_key_ec(
const sa_rights* rights,
sa_elliptic_curve curve,
const std::vector<uint8_t>& clear_key) {
auto key = create_uninitialized_sa_key();
if (clear_key.empty()) {
*key = UNSUPPORTED_KEY;
return key;
}
sa_import_parameters_ec_private_bytes params = {rights, curve};
sa_status const status = sa_key_import(key.get(), SA_KEY_FORMAT_EC_PRIVATE_BYTES, clear_key.data(),
clear_key.size(), ¶ms);
if (status == SA_STATUS_OPERATION_NOT_SUPPORTED) {
ERROR("Unsupported key type");
*key = UNSUPPORTED_KEY;
} else if (status != SA_STATUS_OK) {
ERROR("sa_key_import failed");
key = nullptr;
}
return key;
}
std::shared_ptr<sa_key> create_sa_key_dh(
const sa_rights* rights,
std::tuple<std::vector<uint8_t>, std::vector<uint8_t>>& dh_parameters) {
auto key = create_uninitialized_sa_key();
sa_generate_parameters_dh params = {std::get<0>(dh_parameters).data(), std::get<0>(dh_parameters).size(),
std::get<1>(dh_parameters).data(), std::get<1>(dh_parameters).size()};
sa_status const status = sa_key_generate(key.get(), rights, SA_KEY_TYPE_DH, ¶ms);
if (status == SA_STATUS_OPERATION_NOT_SUPPORTED) {
ERROR("Unsupported key type");
*key = UNSUPPORTED_KEY;
} else if (status != SA_STATUS_OK) {
ERROR("sa_key_import failed");
key = nullptr;
}
return key;
}
std::shared_ptr<sa_key> create_sa_key(
sa_key_type key_type,
size_t& key_length,
std::vector<uint8_t>& clear_key,
sa_elliptic_curve& curve) {
sa_rights rights;
sa_rights_set_allow_all(&rights);
switch (key_type) {
case SA_KEY_TYPE_EC: {
curve = static_cast<sa_elliptic_curve>(key_length);
key_length = ec_get_key_size(curve);
clear_key = ec_generate_key_bytes(curve);
return create_sa_key_ec(&rights, curve, clear_key);
break;
}
case SA_KEY_TYPE_SYMMETRIC: {
curve = static_cast<sa_elliptic_curve>(0);
clear_key = random(key_length);
return create_sa_key_symmetric(&rights, clear_key);
break;
}
case SA_KEY_TYPE_RSA: {
curve = static_cast<sa_elliptic_curve>(0);
clear_key = get_rsa_private_key(key_length);
return create_sa_key_rsa(&rights, clear_key);
break;
}
case SA_KEY_TYPE_DH: {
curve = static_cast<sa_elliptic_curve>(0);
std::tuple<std::vector<uint8_t>, std::vector<uint8_t>> dh_parameters = get_dh_parameters(key_length);
return create_sa_key_dh(&rights, dh_parameters);
break;
}
default:
return nullptr;
}
return nullptr;
}
std::shared_ptr<sa_header> key_header(sa_key key) {
std::shared_ptr<sa_header> hdr(new sa_header);
if (sa_key_header(hdr.get(), key) != SA_STATUS_OK) {
ERROR("sa_key_header failed");
return nullptr;
}
return hdr;
}
bool key_check_sym(
sa_key key,
std::vector<uint8_t>& clear_key) {
auto header = key_header(key);
if (header == nullptr) {
ERROR("Could not get key header");
return false;
}
if (header->type != SA_KEY_TYPE_SYMMETRIC) {
ERROR("Not a sym key");
return false;
}
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_SIGN)) {
if (!key_check_hmac(key, clear_key)) {
ERROR("key_check_hmac failed");
return false;
}
} else {
if (key_check_hmac(key, clear_key)) {
ERROR("key_check_hmac did not fail when it should");
return false;
}
}
if (header->size == SYM_128_KEY_SIZE || header->size == SYM_256_KEY_SIZE) {
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_DECRYPT)) {
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_SVP_OPTIONAL)) {
if (!key_check_decrypt_aes_ecb(key, clear_key)) {
ERROR("key_check_decrypt_aes_ecb failed");
return false;
}
}
} else {
if (key_check_decrypt_aes_ecb(key, clear_key)) {
ERROR("key_check_decrypt_aes_ecb did not fail when it should");
return false;
}
}
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_ENCRYPT)) {
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_SVP_OPTIONAL)) {
if (!key_check_encrypt_aes_ecb(key, clear_key)) {
ERROR("key_check_encrypt_aes_ecb failed");
return false;
}
}
} else {
if (key_check_encrypt_aes_ecb(key, clear_key)) {
ERROR("key_check_encrypt_aes_ecb did not fail when it should");
return false;
}
}
if (SA_USAGE_BIT_TEST(key_header(key)->rights.usage_flags, SA_USAGE_FLAG_UNWRAP)) {
if (!key_check_aes_ecb_unwrap(key, clear_key)) {
ERROR("key_check_aes_ecb_unwrap failed");
return false;
}
} else {
if (key_check_aes_ecb_unwrap(key, clear_key)) {
ERROR("key_check_aes_ecb_unwrap did not fail when it should");
return false;
}
}
}
return true;
}
bool key_check_rsa(
sa_key key,
const std::vector<uint8_t>& clear_key) {
auto header = key_header(key);
if (header == nullptr) {
ERROR("Could not get key header");
return false;
}
if (header->type != SA_KEY_TYPE_RSA) {
ERROR("Not an RSA key");
return false;
}
auto evp_pkey = rsa_import_pkcs8(clear_key);
if (evp_pkey == nullptr) {
ERROR("rsa_import_pkcs8 failed");
return false;
}
std::vector<uint8_t> openssl_public_key;
if (!export_public_key(openssl_public_key, evp_pkey)) {
ERROR("export_public_key failed");
return false;
}
size_t public_key_length;
sa_status status = sa_key_get_public(nullptr, &public_key_length, key);
if (status != SA_STATUS_OK) {
ERROR("sa_key_get_public failed");
return false;
}
std::vector<uint8_t> public_key(public_key_length);
status = sa_key_get_public(public_key.data(), &public_key_length, key);
if (status != SA_STATUS_OK) {
ERROR("sa_key_get_public failed");
return false;
}
if (public_key_length != public_key.size()) {
ERROR("Invalid public key");
return false;
}
if (openssl_public_key != public_key) {
ERROR("Invalid public key");
return false;
}
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_SIGN)) {
std::vector<uint8_t> signature(MAX_SIGNATURE_LENGTH);
sa_sign_parameters_rsa_pss params = {SA_DIGEST_ALGORITHM_SHA256, SA_DIGEST_ALGORITHM_SHA256, false, 32};
size_t signature_length = signature.size();
status = sa_crypto_sign(signature.data(), &signature_length, SA_SIGNATURE_ALGORITHM_RSA_PSS, key,
clear_key.data(), clear_key.size(), ¶ms);
if (status != SA_STATUS_OK) {
ERROR("sa_crypto_sign failed");
return false;
}
signature.resize(signature_length);
if (!verify_rsa_pss_openssl(evp_pkey, SA_DIGEST_ALGORITHM_SHA256, SA_DIGEST_ALGORITHM_SHA256,
params.salt_length, clear_key, signature)) {
ERROR("verify_rsa_pss_openssl failed");
return false;
}
} else {
std::vector<uint8_t> signature(MAX_SIGNATURE_LENGTH);
sa_sign_parameters_rsa_pss params = {SA_DIGEST_ALGORITHM_SHA256, SA_DIGEST_ALGORITHM_SHA256, false, 32};
size_t signature_length = signature.size();
status = sa_crypto_sign(signature.data(), &signature_length, SA_SIGNATURE_ALGORITHM_RSA_PSS, key,
clear_key.data(), clear_key.size(), ¶ms);
if (status == SA_STATUS_OK) {
ERROR("sa_crypto_sign did not fail when it should");
return false;
}
}
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_DECRYPT)) {
if (!key_check_rsa_decrypt(key)) {
ERROR("key_check_rsa_decrypt failed");
return false;
}
} else {
if (key_check_rsa_decrypt(key)) {
ERROR("key_check_rsa_decrypt did not fail when it should");
return false;
}
}
if (SA_USAGE_BIT_TEST(key_header(key)->rights.usage_flags, SA_USAGE_FLAG_UNWRAP)) {
if (!key_check_rsa_oaep_unwrap(key)) {
ERROR("key_check_rsa_oaep_unwrap failed");
return false;
}
} else {
if (key_check_rsa_oaep_unwrap(key)) {
ERROR("key_check_rsa_oaep_unwrap did not fail when it should");
return false;
}
}
return true;
}
bool key_check_ec(
sa_key key,
const std::vector<uint8_t>& clear_key) {
auto header = key_header(key);
if (header == nullptr) {
ERROR("Could not get key header");
return false;
}
if (header->type != SA_KEY_TYPE_EC) {
ERROR("Not a sym key");
return false;
}
auto evp_pkey = ec_import_private(header->type_parameters.curve, clear_key);
if (evp_pkey == nullptr) {
ERROR("ec_import_private failed");
return false;
}
if (reinterpret_cast<uintptr_t>(evp_pkey.get()) == UNSUPPORTED_OPENSSL_KEY) { ERROR("Curve not supported");
return true;
}
std::vector<uint8_t> openssl_public_key;
if (!export_public_key(openssl_public_key, evp_pkey)) {
ERROR("ec_get_public failed");
return false;
}
size_t public_key_length;
sa_status status = sa_key_get_public(nullptr, &public_key_length, key);
if (status != SA_STATUS_OK) {
ERROR("sa_key_get_public failed");
return false;
}
std::vector<uint8_t> public_key(public_key_length);
status = sa_key_get_public(public_key.data(), &public_key_length, key);
if (status != SA_STATUS_OK) {
ERROR("sa_key_get_public failed");
return false;
}
if (public_key_length != public_key.size()) {
ERROR("Invalid public key");
return false;
}
if (openssl_public_key != public_key) {
ERROR("Invalid public key");
return false;
}
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_SIGN)) {
if (is_pcurve(static_cast<sa_elliptic_curve>(header->type_parameters.curve))) {
auto data = random(255);
std::vector<uint8_t> signature(256);
size_t signature_length = signature.size();
sa_sign_parameters_ecdsa parameters = {SA_DIGEST_ALGORITHM_SHA256, false};
status = sa_crypto_sign(signature.data(), &signature_length, SA_SIGNATURE_ALGORITHM_ECDSA, key,
data.data(), data.size(), ¶meters);
if (status != SA_STATUS_OK) {
ERROR("sa_crypto_sign failed");
return false;
}
signature.resize(signature_length);
if (!verify_ec_ecdsa_openssl(evp_pkey.get(), header->type_parameters.curve,
SA_DIGEST_ALGORITHM_SHA256, data, signature)) {
ERROR("verify_ec_ecdsa_openssl failed");
return false;
}
} else if (header->type_parameters.curve == SA_ELLIPTIC_CURVE_ED25519 ||
header->type_parameters.curve == SA_ELLIPTIC_CURVE_ED448) {
auto data = random(255);
std::vector<uint8_t> signature(256);
size_t signature_length = signature.size();
status = sa_crypto_sign(signature.data(), &signature_length, SA_SIGNATURE_ALGORITHM_EDDSA, key,
data.data(), data.size(), nullptr);
if (status != SA_STATUS_OK) {
ERROR("sa_crypto_sign failed");
return false;
}
signature.resize(signature_length);
if (!verify_ec_eddsa_openssl(evp_pkey.get(), header->type_parameters.curve,
data, signature)) {
ERROR("verify_ec_ecdsa_openssl failed");
return false;
}
}
} else {
auto data = random(255);
std::vector<uint8_t> signature(256);
size_t signature_length = signature.size();
sa_sign_parameters_ecdsa parameters = {SA_DIGEST_ALGORITHM_SHA256, false};
status = sa_crypto_sign(signature.data(), &signature_length, SA_SIGNATURE_ALGORITHM_ECDSA, key, data.data(),
data.size(), ¶meters);
if (status == SA_STATUS_OK) {
ERROR("sa_crypto_sign did not fail when it should");
return false;
}
}
if (SA_USAGE_BIT_TEST(header->rights.usage_flags, SA_USAGE_FLAG_DECRYPT) &&
is_pcurve(static_cast<sa_elliptic_curve>(header->type_parameters.curve))) {
if (!key_check_ec_elgamal_decrypt(key)) {
ERROR("key_check_ec_elgamal_decrypt failed");
return false;
}
} else {
if (key_check_ec_elgamal_decrypt(key)) {
ERROR("key_check_ec_elgamal_decrypt did not fail when it should");
return false;
}
}
if (SA_USAGE_BIT_TEST(key_header(key)->rights.usage_flags, SA_USAGE_FLAG_UNWRAP) &&
is_pcurve(static_cast<sa_elliptic_curve>(header->type_parameters.curve))) {
if (!key_check_ec_elgamal_unwrap(key)) {
ERROR("key_check_ec_elgamal_unwrap failed");
return false;
}
} else {
if (key_check_ec_elgamal_unwrap(key)) {
ERROR("key_check_ec_elgamal_unwrap did not fail when it should");
return false;
}
}
return true;
}
bool export_public_key(
std::vector<uint8_t>& out,
std::shared_ptr<EVP_PKEY>& evp_pkey) {
int const required_length = i2d_PUBKEY(evp_pkey.get(), nullptr);
if (required_length <= 0) {
ERROR("i2d_PUBKEY failed");
return false;
}
out.resize(required_length);
auto* buf = out.data();
int const written = i2d_PUBKEY(evp_pkey.get(), &buf);
if (written <= 0) {
ERROR("i2d_PUBKEY failed");
return false;
}
return true;
}
std::shared_ptr<EVP_PKEY> rsa_import_pkcs8(
const std::vector<uint8_t>& in) {
EVP_PKEY* evp_pkey = evp_pkey_from_pkcs8(EVP_PKEY_RSA, in.data(), in.size());
if (evp_pkey == nullptr) {
ERROR("evp_pkey_from_pkcs8 failed");
return nullptr;
}
return {evp_pkey, EVP_PKEY_free};
}
bool verify_rsa_pss_openssl(
const std::shared_ptr<EVP_PKEY>& evp_key,
sa_digest_algorithm digest_algorithm,
sa_digest_algorithm mgf1_digest_algorithm,
size_t salt_length,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& signature) {
std::shared_ptr<EVP_MD_CTX> const context = {EVP_MD_CTX_create(), EVP_MD_CTX_free};
if (context == nullptr) {
ERROR("EVP_MD_CTX_create failed");
return false;
}
EVP_PKEY_CTX* evp_pkey_context = nullptr;
if (EVP_DigestVerifyInit(context.get(), &evp_pkey_context, digest_mechanism(digest_algorithm), nullptr,
evp_key.get()) != 1) {
ERROR("EVP_DigestVerifyInit failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_padding(evp_pkey_context, RSA_PKCS1_PSS_PADDING) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_padding failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_mgf1_md(evp_pkey_context, digest_mechanism(mgf1_digest_algorithm)) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_mgf1_md failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(evp_pkey_context, static_cast<int>(salt_length)) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_pss_saltlen failed");
return false;
}
if (EVP_DigestVerifyUpdate(context.get(), in.data(), in.size()) != 1) {
ERROR("EVP_DigestVerifyUpdate failed");
return false;
}
if (EVP_DigestVerifyFinal(context.get(), signature.data(), signature.size()) != 1) {
ERROR("EVP_DigestVerifyFinal failed");
return false;
}
return true;
}
bool verify_rsa_pkcs1v15_openssl(
const std::shared_ptr<EVP_PKEY>& evp_key,
sa_digest_algorithm digest_algorithm,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& signature) {
std::shared_ptr<EVP_MD_CTX> const context = {EVP_MD_CTX_create(), EVP_MD_CTX_free};
if (context == nullptr) {
ERROR("EVP_MD_CTX_create failed");
return false;
}
EVP_PKEY_CTX* evp_pkey_context = nullptr;
if (EVP_DigestVerifyInit(context.get(), &evp_pkey_context, digest_mechanism(digest_algorithm), nullptr,
evp_key.get()) != 1) {
ERROR("EVP_DigestVerifyInit failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_padding(evp_pkey_context, RSA_PKCS1_PADDING) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_padding failed");
return false;
}
if (EVP_DigestVerifyUpdate(context.get(), in.data(), in.size()) != 1) {
ERROR("EVP_DigestVerifyUpdate failed");
return false;
}
if (EVP_DigestVerifyFinal(context.get(), signature.data(), signature.size()) != 1) {
ERROR("EVP_DigestVerifyFinal failed");
return false;
}
return true;
}
bool encrypt_rsa_oaep_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::shared_ptr<EVP_PKEY>& evp_pkey,
sa_digest_algorithm digest_algorithm,
sa_digest_algorithm mgf1_digest_algorithm,
const std::vector<uint8_t>& label) {
size_t const digest_len = digest_length(digest_algorithm);
size_t const key_size = EVP_PKEY_bits(evp_pkey.get()) / 8;
out.resize(key_size);
if (in.size() > key_size - 2 * digest_len - 1) {
ERROR("Invalid in.size()");
return false;
}
std::shared_ptr<EVP_PKEY_CTX> const evp_pkey_ctx = {EVP_PKEY_CTX_new(evp_pkey.get(), nullptr),
EVP_PKEY_CTX_free};
if (evp_pkey_ctx == nullptr) {
ERROR("EVP_PKEY_CTX_new failed");
return false;
}
if (EVP_PKEY_encrypt_init(evp_pkey_ctx.get()) != 1) {
ERROR("EVP_PKEY_encrypt_init failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx.get(), RSA_PKCS1_OAEP_PADDING) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_padding failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_oaep_md(evp_pkey_ctx.get(), digest_mechanism(digest_algorithm)) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_oaep_md failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_mgf1_md(evp_pkey_ctx.get(), digest_mechanism(mgf1_digest_algorithm)) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_mgf1_md failed");
return false;
}
if (!label.empty()) {
void* new_label = malloc(label.size());
if (new_label == nullptr) {
ERROR("malloc failed");
return false;
}
memcpy(new_label, label.data(), label.size());
if (EVP_PKEY_CTX_set0_rsa_oaep_label(evp_pkey_ctx.get(), new_label, static_cast<int>(label.size())) != 1) {
free(new_label);
ERROR("EVP_PKEY_CTX_set0_rsa_oaep_label failed");
return false;
}
}
size_t out_length = out.size();
if (EVP_PKEY_encrypt(evp_pkey_ctx.get(), out.data(), &out_length, in.data(), in.size()) != 1) {
ERROR("EVP_PKEY_encrypt failed");
return false;
}
return true;
}
bool encrypt_rsa_pkcs1v15_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::shared_ptr<EVP_PKEY>& evp_pkey) {
size_t const key_size = EVP_PKEY_bits(evp_pkey.get()) / 8;
out.resize(key_size);
if (in.size() > key_size - RSA_PKCS1_PADDING_SIZE) {
ERROR("Invalid in.size()");
return false;
}
std::shared_ptr<EVP_PKEY_CTX> const evp_pkey_ctx = {EVP_PKEY_CTX_new(evp_pkey.get(), nullptr),
EVP_PKEY_CTX_free};
if (evp_pkey_ctx == nullptr) {
ERROR("EVP_PKEY_CTX_new failed");
return false;
}
if (EVP_PKEY_encrypt_init(evp_pkey_ctx.get()) != 1) {
ERROR("EVP_PKEY_encrypt_init failed");
return false;
}
if (EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx.get(), RSA_PKCS1_PADDING) != 1) {
ERROR("EVP_PKEY_CTX_set_rsa_padding failed");
return false;
}
size_t out_length = out.size();
if (EVP_PKEY_encrypt(evp_pkey_ctx.get(), out.data(), &out_length, in.data(), in.size()) != 1) {
ERROR("EVP_PKEY_encrypt failed");
return false;
}
return true;
}
std::shared_ptr<EVP_PKEY> ec_import_private(
sa_elliptic_curve curve,
const std::vector<uint8_t>& in) {
int type;
if (is_pcurve(curve))
type = EVP_PKEY_EC;
#if OPENSSL_VERSION_NUMBER >= 0x10100000
else if (curve == SA_ELLIPTIC_CURVE_ED25519)
type = EVP_PKEY_ED25519;
else if (curve == SA_ELLIPTIC_CURVE_X25519)
type = EVP_PKEY_X25519;
else if (curve == SA_ELLIPTIC_CURVE_ED448)
type = EVP_PKEY_ED448;
else if (curve == SA_ELLIPTIC_CURVE_X448)
type = EVP_PKEY_X448;
#endif
else {
ERROR("Unknown curve");
return {};
}
EVP_PKEY* evp_pkey = evp_pkey_from_pkcs8(type, in.data(), in.size());
if (evp_pkey == nullptr) {
ERROR("evp_pkey_from_pkcs8 failed");
return nullptr;
}
return {evp_pkey, EVP_PKEY_free};
}
std::vector<uint8_t> ec_generate_key_bytes(sa_elliptic_curve curve) {
int const type = ec_get_nid(curve);
if (type == 0) {
ERROR("ec_get_nid failed");
return {};
}
std::shared_ptr<EVP_PKEY_CTX> evp_pkey_ctx;
if (is_pcurve(curve)) {
auto param_ctx = std::shared_ptr<EVP_PKEY_CTX>(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr),
EVP_PKEY_CTX_free);
if (param_ctx == nullptr) {
ERROR("EVP_PKEY_CTX_new_id failed");
return {};
}
if (EVP_PKEY_paramgen_init(param_ctx.get()) != 1) {
ERROR("EVP_PKEY_paramgen_init failed");
return {};
}
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(param_ctx.get(), type) != 1) {
ERROR("EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed");
return {};
}
if (EVP_PKEY_CTX_set_ec_param_enc(param_ctx.get(), OPENSSL_EC_NAMED_CURVE) != 1) {
ERROR("EVP_PKEY_CTX_set_ec_param_enc failed");
return {};
}
EVP_PKEY* params = nullptr;
if (EVP_PKEY_paramgen(param_ctx.get(), ¶ms) <= 0) {
ERROR("EVP_PKEY_paramgen failed");
return {};
}
auto evp_pkey_params = std::shared_ptr<EVP_PKEY>(params, EVP_PKEY_free);
evp_pkey_ctx = std::shared_ptr<EVP_PKEY_CTX>(EVP_PKEY_CTX_new(evp_pkey_params.get(), nullptr),
EVP_PKEY_CTX_free);
if (evp_pkey_ctx == nullptr) {
ERROR("EVP_PKEY_CTX_new failed");
return {};
}
} else {
evp_pkey_ctx = std::shared_ptr<EVP_PKEY_CTX>(EVP_PKEY_CTX_new_id(type, nullptr), EVP_PKEY_CTX_free);
}
if (EVP_PKEY_keygen_init(evp_pkey_ctx.get()) != 1) {
ERROR("EVP_PKEY_keygen_init failed");
return {};
}
EVP_PKEY* temp_pkey = nullptr;
if (EVP_PKEY_keygen(evp_pkey_ctx.get(), &temp_pkey) != 1) {
ERROR("EVP_PKEY_keygen failed");
return {};
}
auto evp_pkey = std::shared_ptr<EVP_PKEY>(temp_pkey, EVP_PKEY_free);
size_t length = 0;
if (!evp_pkey_to_pkcs8(nullptr, &length, evp_pkey.get())) {
ERROR("evp_pkey_to_pkcs8 failed");
return {};
}
std::vector<uint8_t> private_key(length);
if (!evp_pkey_to_pkcs8(private_key.data(), &length, evp_pkey.get())) {
ERROR("evp_pkey_to_pkcs8 failed");
return {};
}
return private_key;
}
bool verify_ec_ecdsa_openssl(
EVP_PKEY* evp_pkey,
sa_elliptic_curve curve,
sa_digest_algorithm digest_algorithm,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& signature) {
if (evp_pkey == nullptr) {
ERROR("NULL evp_pkey");
return false;
}
size_t const key_size = ec_get_key_size(curve);
if (signature.size() != key_size * 2) {
ERROR("Invalid signature length");
return false;
}
if (curve == SA_ELLIPTIC_CURVE_ED25519 || curve == SA_ELLIPTIC_CURVE_ED448) {
ERROR("Invalid curve for ECDSA");
return false;
}
bool status = false;
EVP_MD_CTX* context = nullptr;
uint8_t local_signature[MAX_SIGNATURE_LENGTH];
size_t local_signature_length;
do {
const EVP_MD* openssl_digest;
if (!ec_encode_signature(local_signature, &local_signature_length, signature.data(),
signature.size())) {
ERROR("ec_encode_signature failed");
break;
}
openssl_digest = digest_mechanism(digest_algorithm);
context = EVP_MD_CTX_create();
if (context == nullptr) {
ERROR("EVP_MD_CTX_create failed");
break;
}
if (EVP_DigestVerifyInit(context, nullptr, openssl_digest, nullptr, evp_pkey) != 1) {
ERROR("EVP_DigestVerifyInit failed");
break;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (EVP_DigestVerifyUpdate(context, in.data(), in.size()) != 1) {
ERROR("EVP_DigestVerify failed");
break;
}
if (EVP_DigestVerifyFinal(context, local_signature, local_signature_length) != 1) {
ERROR("EVP_DigestVerify failed");
break;
}
#else
if (EVP_DigestVerify(context, local_signature, local_signature_length, in.data(), in.size()) != 1) {
ERROR("EVP_DigestVerify failed");
break;
}
#endif
status = true;
} while (false);
EVP_MD_CTX_destroy(context);
return status;
}
bool verify_ec_eddsa_openssl(
EVP_PKEY* evp_pkey,
sa_elliptic_curve curve,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& signature) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return false;
#else
if (evp_pkey == nullptr) {
ERROR("NULL evp_pkey");
return false;
}
size_t const key_size = ec_get_key_size(curve);
if (signature.size() != key_size * 2) {
ERROR("Invalid signature length");
return false;
}
if (curve != SA_ELLIPTIC_CURVE_ED25519 && curve != SA_ELLIPTIC_CURVE_ED448) {
ERROR("Invalid curve for EDDSA");
return false;
}
bool status = false;
EVP_MD_CTX* context;
ECDSA_SIG* eddsa_signature = nullptr;
do {
context = EVP_MD_CTX_create();
if (context == nullptr) {
ERROR("EVP_MD_CTX_create failed");
break;
}
if (EVP_DigestVerifyInit(context, nullptr, nullptr, nullptr, evp_pkey) != 1) {
ERROR("EVP_DigestVerifyInit failed");
break;
}
if (EVP_DigestVerify(context, signature.data(), signature.size(), in.data(), in.size()) != 1) {
ERROR("EVP_DigestVerify failed");
break;
}
status = true;
} while (false);
ECDSA_SIG_free(eddsa_signature);
EVP_MD_CTX_destroy(context);
return status;
#endif
}
bool encrypt_ec_elgamal_openssl(
std::vector<uint8_t>& out,
std::vector<uint8_t>& in,
sa_elliptic_curve curve,
const std::shared_ptr<EVP_PKEY>& public_key) {
auto ec_group = std::shared_ptr<EC_GROUP>(EC_GROUP_new_by_curve_name(ec_get_nid(curve)), EC_GROUP_free);
if (ec_group == nullptr) {
ERROR("NULL ec_group");
return false;
}
int const key_size = EC_KEY_SIZE(ec_group.get());
if (in.size() != static_cast<size_t>(key_size)) {
ERROR("Invalid in_length");
return false;
}
auto w = ec_generate_key_bytes(curve);
auto evp_pkey = ec_import_private(curve, w);
if (evp_pkey == nullptr) {
ERROR("EVP_PKEY_get1_EC_KEY failed");
return false;
}
#if OPENSSL_VERSION_NUMBER < 0x30000000
auto ec_key = std::shared_ptr<EC_KEY>(EVP_PKEY_get1_EC_KEY(evp_pkey.get()), EC_KEY_free);
if (ec_key == nullptr) {
ERROR("EVP_PKEY_get1_EC_KEY failed");
return false;
}
const BIGNUM* w_private = EC_KEY_get0_private_key(ec_key.get());
const EC_POINT* w_public = EC_KEY_get0_public_key(ec_key.get());
#else
BIGNUM* w_private_bn = nullptr;
if (EVP_PKEY_get_bn_param(evp_pkey.get(), "priv", &w_private_bn) != 1) {
ERROR("EVP_PKEY_get_bn_param failed");
return false;
}
auto w_private = std::shared_ptr<BIGNUM>(w_private_bn, BN_free);
std::vector<uint8_t> w_public_octet(key_size * 2 + 1);
size_t w_public_octet_length = 0;
if (EVP_PKEY_get_octet_string_param(evp_pkey.get(), "pub", w_public_octet.data(), w_public_octet.size(),
&w_public_octet_length) != 1) {
ERROR("EVP_PKEY_get_octet_string_param failed");
return false;
}
auto w_public = std::shared_ptr<EC_POINT>(EC_POINT_new(ec_group.get()), EC_POINT_free);
if (EC_POINT_oct2point(ec_group.get(), w_public.get(), w_public_octet.data(), w_public_octet_length,
nullptr) != 1) {
ERROR("EC_POINT_oct2point failed");
return false;
}
#endif
std::shared_ptr<EC_POINT> input_point;
do {
std::shared_ptr<BIGNUM> const input_x(BN_bin2bn(in.data(), static_cast<int>(in.size()), nullptr), BN_free);
if (input_x == nullptr) {
ERROR("BN_bin2bn failed");
return false;
}
input_point = std::shared_ptr<EC_POINT>(EC_POINT_new(ec_group.get()), EC_POINT_free);
if (input_point == nullptr) {
ERROR("EC_POINT_new failed");
return false;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000
if (EC_POINT_set_compressed_coordinates(ec_group.get(), input_point.get(), input_x.get(), 0,
nullptr) != 0)
break;
#else
if (EC_POINT_set_compressed_coordinates_GFp(ec_group.get(), input_point.get(), input_x.get(), 0,
nullptr) != 0)
break;
#endif
auto* counter = reinterpret_cast<uint32_t*>(in.data() + in.size() - sizeof(uint32_t));
(*counter)++;
} while (true);
std::shared_ptr<EC_POINT> const ss(EC_POINT_new(ec_group.get()), EC_POINT_free);
if (ss == nullptr) {
ERROR("EC_POINT_new failed");
return false;
}
auto public_ec_key = std::shared_ptr<EC_KEY>(EVP_PKEY_get1_EC_KEY(public_key.get()), EC_KEY_free);
const EC_POINT* ec_point = EC_KEY_get0_public_key(public_ec_key.get());
#if OPENSSL_VERSION_NUMBER < 0x30000000
if (EC_POINT_mul(ec_group.get(), ss.get(), nullptr, ec_point, w_private, nullptr) == 0) {
#else
if (EC_POINT_mul(ec_group.get(), ss.get(), nullptr, ec_point, w_private.get(), nullptr) == 0) {
#endif
ERROR("EC_POINT_mul failed");
return false;
}
std::shared_ptr<EC_POINT> const c2(EC_POINT_new(ec_group.get()), EC_POINT_free);
if (c2 == nullptr) {
ERROR("EC_POINT_new failed");
return false;
}
if (EC_POINT_add(ec_group.get(), c2.get(), ss.get(), input_point.get(), nullptr) == 0) {
ERROR("EC_POINT_add failed");
return false;
}
std::vector<uint8_t> out1;
#if OPENSSL_VERSION_NUMBER < 0x30000000
if (!ec_point_export_xy(out1, w_public, ec_group.get())) {
#else
if (!ec_point_export_xy(out1, w_public.get(), ec_group.get())) {
#endif
ERROR("ecpoint_export failed");
return false;
}
std::vector<uint8_t> out2;
if (!ec_point_export_xy(out2, c2.get(), ec_group.get())) {
ERROR("ecpoint_export failed");
return false;
}
out.resize(0);
out.insert(out.end(), out1.begin(), out1.end());
out.insert(out.end(), out2.begin(), out2.end());
return true;
}
bool encrypt_aes_cbc_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& key,
bool pad) {
if (!pad && (in.size() % AES_BLOCK_SIZE != 0)) {
ERROR("Invalid in_length");
return false;
}
if ((key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE)) {
ERROR("Invalid key_length");
return false;
}
if (pad)
out.resize(((in.size() / AES_BLOCK_SIZE) * AES_BLOCK_SIZE) + AES_BLOCK_SIZE);
else
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_cbc();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_cbc();
if (cipher == nullptr) {
ERROR("EVP_aes_???_cbc failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, key.data(), iv.data()) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, pad ? 1 : 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
auto* out_bytes = out.data();
int length = 0;
if (EVP_EncryptUpdate(context, out_bytes, &length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
size_t decrypted_length = length;
out_bytes += length;
if (pad) {
if (EVP_EncryptFinal_ex(context, out_bytes, &length) != 1) {
ERROR("EVP_EncryptFinal_ex failed");
break;
}
decrypted_length += length;
}
out.resize(decrypted_length);
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool decrypt_aes_cbc_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& key,
bool pad) {
if (in.size() % 16 != 0) {
ERROR("Invalid in_length");
return false;
}
if ((key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE)) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_cbc();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_cbc();
if (cipher == nullptr) {
ERROR("EVP_aes_???_cbc failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, key.data(), iv.data()) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, pad ? 1 : 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
auto* out_bytes = out.data();
int length = 0;
if (EVP_DecryptUpdate(context, out_bytes, &length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
size_t decrypted_length = length;
out_bytes += length;
if (pad) {
if (EVP_DecryptFinal_ex(context, out_bytes, &length) != 1) {
ERROR("EVP_DecryptFinal_ex failed");
break;
}
decrypted_length += length;
}
out.resize(decrypted_length);
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool encrypt_aes_ecb_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& key,
bool pad) {
if (!pad && (in.size() % AES_BLOCK_SIZE != 0)) {
ERROR("Invalid in_length");
return false;
}
if ((key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE)) {
ERROR("Invalid key_length");
return false;
}
if (pad)
out.resize(((in.size() / AES_BLOCK_SIZE) * AES_BLOCK_SIZE) + AES_BLOCK_SIZE);
else
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_ecb();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_ecb();
if (cipher == nullptr) {
ERROR("EVP_aes_???_ebc failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, key.data(), nullptr) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, pad ? 1 : 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
auto* out_bytes = out.data();
int length = 0;
if (EVP_EncryptUpdate(context, out_bytes, &length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
out_bytes += length;
size_t decrypted_length = length;
if (pad) {
if (EVP_EncryptFinal_ex(context, out_bytes, &length) != 1) {
ERROR("EVP_EncryptFinal_ex failed");
break;
}
decrypted_length += length;
}
out.resize(decrypted_length);
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool decrypt_aes_ecb_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& key,
bool pad) {
if (in.size() % 16 != 0) {
ERROR("Invalid in_length");
return false;
}
if ((key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE)) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_ecb();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_ecb();
if (cipher == nullptr) {
ERROR("EVP_aes_???_ebc failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, key.data(), nullptr) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, pad ? 1 : 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
auto* out_bytes = out.data();
int length = 0;
if (EVP_DecryptUpdate(context, out_bytes, &length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
out_bytes += length;
size_t decrypted_length = length;
if (pad) {
if (EVP_DecryptFinal_ex(context, out_bytes, &length) != 1) {
ERROR("EVP_DecryptFinal_ex failed");
break;
}
decrypted_length += length;
}
out.resize(decrypted_length);
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool encrypt_aes_ctr_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& counter,
const std::vector<uint8_t>& key) {
if (key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_ctr();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_ctr();
if (cipher == nullptr) {
ERROR("EVP_aes_???_ctr failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, key.data(), counter.data()) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (EVP_EncryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool decrypt_aes_ctr_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& counter,
const std::vector<uint8_t>& key) {
if (key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_ctr();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_ctr();
if (cipher == nullptr) {
ERROR("EVP_aes_???_ctr failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, key.data(), counter.data()) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (EVP_DecryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool encrypt_aes_gcm_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& aad,
std::vector<uint8_t>& tag,
const std::vector<uint8_t>& key) {
if (iv.size() != GCM_IV_LENGTH) {
ERROR("Invalid iv_length");
return false;
}
if (key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_gcm();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_gcm();
if (cipher == nullptr) {
ERROR("EVP_aes_???_gcm failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, nullptr, nullptr) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, static_cast<int>(iv.size()), nullptr) != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, key.data(), iv.data()) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (!aad.empty()) {
if (EVP_EncryptUpdate(context, nullptr, &out_length, aad.data(), static_cast<int>(aad.size())) !=
1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
}
if (EVP_EncryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
if (EVP_EncryptFinal_ex(context, nullptr, &out_length) != 1) {
ERROR("EVP_EncryptFinal_ex failed");
break;
}
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, static_cast<int>(tag.size()), tag.data()) != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool decrypt_aes_gcm_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& aad,
const std::vector<uint8_t>& tag,
const std::vector<uint8_t>& key) {
if (iv.size() != GCM_IV_LENGTH) {
ERROR("Invalid iv_length");
return false;
}
if (tag.size() > AES_BLOCK_SIZE) {
ERROR("Invalid tag_length");
return false;
}
if (key.size() != SYM_128_KEY_SIZE && key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = nullptr;
if (key.size() == SYM_128_KEY_SIZE)
cipher = EVP_aes_128_gcm();
else if (key.size() == SYM_256_KEY_SIZE)
cipher = EVP_aes_256_gcm();
if (cipher == nullptr) {
ERROR("EVP_aes_???_gcm failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, nullptr, nullptr) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, static_cast<int>(iv.size()), nullptr) != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, key.data(), iv.data()) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (!aad.empty()) {
if (EVP_DecryptUpdate(context, nullptr, &out_length, aad.data(), static_cast<int>(aad.size())) !=
1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
}
if (EVP_DecryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
if (!tag.empty()) {
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, static_cast<int>(tag.size()),
(void*) tag.data()) != 1) { ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
int length = 0;
if (EVP_DecryptFinal_ex(context, nullptr, &length) != 1) {
ERROR("EVP_DecryptFinal_ex failed");
break;
}
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
}
bool encrypt_chacha20_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& counter,
const std::vector<uint8_t>& nonce,
const std::vector<uint8_t>& key) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return false;
#else
if (nonce.size() != CHACHA20_NONCE_LENGTH) {
ERROR("Invalid nonce_length");
return false;
}
if (counter.size() != CHACHA20_COUNTER_LENGTH) {
ERROR("Invalid counter_length");
return false;
}
if (key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
std::vector<uint8_t> iv;
iv.insert(iv.end(), counter.begin(), counter.end());
iv.insert(iv.end(), nonce.begin(), nonce.end());
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = EVP_chacha20();
if (cipher == nullptr) {
ERROR("EVP_chacha20 failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, key.data(), iv.data()) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (EVP_EncryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
#endif
}
bool decrypt_chacha20_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& counter,
const std::vector<uint8_t>& nonce,
const std::vector<uint8_t>& key) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return false;
#else
if (nonce.size() != CHACHA20_NONCE_LENGTH) {
ERROR("Invalid nonce_length");
return false;
}
if (counter.size() != CHACHA20_COUNTER_LENGTH) {
ERROR("Invalid counter_length");
return false;
}
if (key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
std::vector<uint8_t> iv;
iv.insert(iv.end(), counter.begin(), counter.end());
iv.insert(iv.end(), nonce.begin(), nonce.end());
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = EVP_chacha20();
if (cipher == nullptr) {
ERROR("EVP_chacha20 failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, key.data(), iv.data()) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (EVP_DecryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
#endif
}
bool encrypt_chacha20_poly1305_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& nonce,
const std::vector<uint8_t>& aad,
std::vector<uint8_t>& tag,
const std::vector<uint8_t>& key) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return false;
#else
if (nonce.size() != CHACHA20_NONCE_LENGTH) {
ERROR("Invalid nonce_length");
return false;
}
if (key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = EVP_chacha20_poly1305();
if (cipher == nullptr) {
ERROR("EVP_chacha20_poly1305 failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, nullptr, nullptr) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_AEAD_SET_IVLEN, static_cast<int>(nonce.size()), nullptr) != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
if (EVP_EncryptInit_ex(context, cipher, nullptr, key.data(), nonce.data()) != 1) {
ERROR("EVP_EncryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (!aad.empty()) {
if (EVP_EncryptUpdate(context, nullptr, &out_length, aad.data(), static_cast<int>(aad.size())) !=
1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
}
if (EVP_EncryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_EncryptUpdate failed");
break;
}
if (EVP_EncryptFinal_ex(context, nullptr, &out_length) != 1) {
ERROR("EVP_EncryptFinal_ex failed");
break;
}
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_AEAD_GET_TAG, static_cast<int>(tag.size()), tag.data()) != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
#endif
}
bool decrypt_chacha20_poly1305_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& in,
const std::vector<uint8_t>& nonce,
const std::vector<uint8_t>& aad,
const std::vector<uint8_t>& tag,
const std::vector<uint8_t>& key) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return false;
#else
if (nonce.size() != CHACHA20_NONCE_LENGTH) {
ERROR("Invalid nonce_length");
return false;
}
if (key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
if (!tag.empty() && tag.size() != CHACHA20_TAG_LENGTH) {
ERROR("Invalid tag_length");
return false;
}
if (key.size() != SYM_256_KEY_SIZE) {
ERROR("Invalid key_length");
return false;
}
out.resize(in.size());
bool status = false;
EVP_CIPHER_CTX* context;
do {
context = EVP_CIPHER_CTX_new();
if (context == nullptr) {
ERROR("EVP_CIPHER_CTX_new failed");
break;
}
const EVP_CIPHER* cipher = EVP_chacha20_poly1305();
if (cipher == nullptr) {
ERROR("EVP_chacha20_poly1305 failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, nullptr, nullptr) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_AEAD_SET_IVLEN, static_cast<int>(nonce.size()), nullptr) != 1) {
ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
if (EVP_DecryptInit_ex(context, cipher, nullptr, key.data(), nonce.data()) != 1) {
ERROR("EVP_DecryptInit_ex failed");
break;
}
if (EVP_CIPHER_CTX_set_padding(context, 0) != 1) {
ERROR("EVP_CIPHER_CTX_set_padding failed");
break;
}
int out_length = static_cast<int>(in.size());
if (!aad.empty()) {
if (EVP_DecryptUpdate(context, nullptr, &out_length, aad.data(), static_cast<int>(aad.size())) !=
1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
}
if (EVP_DecryptUpdate(context, out.data(), &out_length, in.data(), static_cast<int>(in.size())) != 1) {
ERROR("EVP_DecryptUpdate failed");
break;
}
if (!tag.empty()) {
if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_AEAD_SET_TAG, static_cast<int>(tag.size()),
(void*) tag.data()) != 1) { ERROR("EVP_CIPHER_CTX_ctrl failed");
break;
}
int length = 0;
if (EVP_DecryptFinal_ex(context, nullptr, &length) != 1) {
ERROR("EVP_DecryptFinal_ex failed");
break;
}
}
status = true;
} while (false);
EVP_CIPHER_CTX_free(context);
return status;
#endif
}
bool hmac_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& in,
sa_digest_algorithm digest_algorithm) {
const auto* md = digest_mechanism(digest_algorithm);
unsigned int out_length = digest_length(digest_algorithm);
out.resize(out_length);
return HMAC(md, key.data(), static_cast<int>(key.size()), in.data(), in.size(), out.data(),
&out_length) != nullptr;
}
bool cmac_openssl(
std::vector<uint8_t>& out,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& in) {
#if OPENSSL_VERSION_NUMBER >= 0x30000000
auto evp_mac = std::shared_ptr<EVP_MAC>(EVP_MAC_fetch(nullptr, "cmac", nullptr), EVP_MAC_free);
if (evp_mac == nullptr) {
ERROR("EVP_MAC_fetch failed");
return false;
}
auto evp_mac_ctx = std::shared_ptr<EVP_MAC_CTX>(EVP_MAC_CTX_new(evp_mac.get()), EVP_MAC_CTX_free);
if (evp_mac_ctx == nullptr) {
ERROR("EVP_MAC_CTX_new failed");
return false;
}
OSSL_PARAM params[] = {
OSSL_PARAM_construct_utf8_string("cipher",
const_cast<char*>((key.size() == SYM_128_KEY_SIZE) ? "aes-128-cbc" : "aes-256-cbc"), 0),
OSSL_PARAM_construct_end()};
if (EVP_MAC_init(evp_mac_ctx.get(), key.data(), key.size(), params) != 1) {
ERROR("EVP_MAC_init failed");
return false;
}
if (EVP_MAC_update(evp_mac_ctx.get(), in.data(), in.size()) != 1) {
ERROR("EVP_MAC_update failed");
return false;
}
size_t mac_length = 16;
out.resize(mac_length);
if (EVP_MAC_final(evp_mac_ctx.get(), out.data(), &mac_length, mac_length) != 1) {
ERROR("EVP_MAC_final failed");
return false;
}
#else
const EVP_CIPHER* cipher = (key.size() == SYM_128_KEY_SIZE) ? EVP_aes_128_cbc() : EVP_aes_256_cbc();
auto context = std::shared_ptr<CMAC_CTX>(CMAC_CTX_new(), CMAC_CTX_free);
if (context == nullptr) {
ERROR("CMAC_CTX_new failed");
return false;
}
if (CMAC_Init(context.get(), key.data(), key.size(), cipher, nullptr) != 1) {
ERROR("CMAC_Init failed");
return false;
}
if (CMAC_Update(context.get(), in.data(), in.size()) != 1) {
ERROR("CMAC_Update failed");
return false;
}
size_t mac_length = 16;
out.resize(mac_length);
if (CMAC_Final(context.get(), out.data(), &mac_length) != 1) {
ERROR("CMAC_Final failed");
return false;
}
#endif
return true;
}
bool ec_point_export_xy(
std::vector<uint8_t>& out,
const EC_POINT* ec_point,
const EC_GROUP* ec_group) {
if (ec_point == nullptr) {
ERROR("NULL ec_point");
return false;
}
if (ec_group == nullptr) {
ERROR("NULL ec_group");
return false;
}
size_t const coordinate_length = EC_KEY_SIZE(ec_group);
bool status = false;
do {
std::vector<uint8_t> temp_point(coordinate_length * 2 + 1);
if (EC_POINT_point2oct(ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, temp_point.data(),
temp_point.size(), nullptr) != coordinate_length * 2 + 1) {
ERROR("EC_POINT_point2oct failed");
break;
}
out.insert(out.begin(), temp_point.begin() + 1, temp_point.end());
out.resize(coordinate_length * 2);
status = true;
} while (false);
return status;
}
std::shared_ptr<sa_buffer> buffer_alloc(
sa_buffer_type buffer_type,
size_t size) {
auto buffer = std::shared_ptr<sa_buffer>(
new sa_buffer,
[buffer_type](const sa_buffer* buffer) {
if (buffer != nullptr) {
if (buffer_type == SA_BUFFER_TYPE_CLEAR) {
if (buffer->context.clear.buffer != nullptr)
free(buffer->context.clear.buffer);
} else {
if (buffer->context.svp.buffer != INVALID_HANDLE)
sa_svp_buffer_free(buffer->context.svp.buffer);
}
}
delete buffer;
});
if (buffer_type == SA_BUFFER_TYPE_CLEAR) {
buffer->buffer_type = SA_BUFFER_TYPE_CLEAR;
buffer->context.clear.length = size;
buffer->context.clear.offset = 0;
buffer->context.clear.buffer = malloc(size);
if (buffer->context.clear.buffer == nullptr) {
ERROR("malloc failed");
return nullptr;
}
} else if (buffer_type == SA_BUFFER_TYPE_SVP) {
buffer->buffer_type = SA_BUFFER_TYPE_SVP;
buffer->context.svp.buffer = INVALID_HANDLE;
sa_svp_buffer svp_buffer;
if (sa_svp_buffer_alloc(&svp_buffer, size) != SA_STATUS_OK) {
ERROR("sa_svp_buffer_alloc failed");
return nullptr;
}
buffer->context.svp.buffer = svp_buffer;
buffer->context.svp.offset = 0;
}
return buffer;
}
std::shared_ptr<sa_buffer> buffer_alloc(
sa_buffer_type buffer_type,
std::vector<uint8_t>& initial_value) {
auto buffer = buffer_alloc(buffer_type, initial_value.size());
if (buffer == nullptr)
return nullptr;
if (buffer_type == SA_BUFFER_TYPE_CLEAR) {
memcpy(buffer->context.clear.buffer, initial_value.data(), initial_value.size());
} else {
sa_svp_offset offsets = {0, 0, initial_value.size()};
if (sa_svp_buffer_write(buffer->context.svp.buffer, initial_value.data(), initial_value.size(),
&offsets, 1) != SA_STATUS_OK) {
ERROR("sa_svp_buffer_write");
return nullptr;
}
buffer->context.svp.offset = 0;
}
return buffer;
}
}