1/*
2 This file is part of Mtproto-proxy Library.
3
4 Mtproto-proxy Library is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 Mtproto-proxy Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright 2012-2013 Vkontakte Ltd
18 2012-2013 Anton Maydell
19
20 Copyright 2014-2016 Telegram Messenger Inc
21 2014-2016 Anton Maydell
22*/
23
24#include "crypto/aesni256.h"
25#include <assert.h>
26#include <string.h>
27#include <stdint.h>
28#include "common/cpuid.h"
29
30#include <openssl/opensslv.h>
31
32#if OPENSSL_VERSION_NUMBER >= 0x10100000L
33#include <openssl/modes.h>
34void AES_ctr128_encrypt(
35 const unsigned char *in,
36 unsigned char *out,
37 size_t length,
38 const AES_KEY *key,
39 unsigned char ivec[AES_BLOCK_SIZE],
40 unsigned char ecount_buf[AES_BLOCK_SIZE],
41 unsigned int *num) {
42 CRYPTO_ctr128_encrypt(in, out, length, key, ivec, ecount_buf, num, (block128_f)AES_encrypt);
43}
44#endif
45
46void tg_ssl_aes_ctr_crypt (tg_aes_ctx_t *ctx, const unsigned char *in, unsigned char *out, int size, unsigned char iv[16], unsigned long long offset) {
47 unsigned char iv_copy[16];
48 memcpy (iv_copy, iv, 16);
49 unsigned long long *p = (unsigned long long *) (iv_copy + 8);
50 (*p) += offset >> 4;
51 union {
52 unsigned char c[16];
53 unsigned long long d[2];
54 } u;
55 int i = offset & 15, l;
56 if (i) {
57 AES_encrypt (iv_copy, u.c, &ctx->u.key);
58 (*p)++;
59 l = i + size;
60 if (l > 16) {
61 l = 16;
62 }
63 size -= l - i;
64 do {
65 *out++ = (*in++) ^ u.c[i++];
66 } while (i < l);
67 }
68 const unsigned long long *I = (const unsigned long long *) in;
69 unsigned long long *O = (unsigned long long *) out;
70 int n = size >> 4;
71 while (--n >= 0) {
72 AES_encrypt (iv_copy, (unsigned char *) u.d, &ctx->u.key);
73 (*p)++;
74 *O++ = (*I++) ^ u.d[0];
75 *O++ = (*I++) ^ u.d[1];
76 }
77 l = size & 15;
78 if (l) {
79 AES_encrypt (iv_copy, u.c, &ctx->u.key);
80 in = (const unsigned char *) I;
81 out = (unsigned char *) O;
82 i = 0;
83 do {
84 *out++ = (*in++) ^ u.c[i++];
85 } while (i < l);
86 }
87}
88
89
90static void tg_ssl_aes_cbc_encrypt (tg_aes_ctx_t *ctx, const unsigned char *in, unsigned char *out, int size, unsigned char iv[16]) {
91 AES_cbc_encrypt (in, out, size, &ctx->u.key, iv, AES_ENCRYPT);
92}
93
94static void tg_ssl_aes_cbc_decrypt (tg_aes_ctx_t *ctx, const unsigned char *in, unsigned char *out, int size, unsigned char iv[16]) {
95 AES_cbc_encrypt (in, out, size, &ctx->u.key, iv, AES_DECRYPT);
96}
97
98static void tg_ssl_aes_ige_encrypt (tg_aes_ctx_t *ctx, const unsigned char *in, unsigned char *out, int size, unsigned char iv[32]) {
99 AES_ige_encrypt (in, out, size, &ctx->u.key, iv, AES_ENCRYPT);
100}
101
102static void tg_ssl_aes_ige_decrypt (tg_aes_ctx_t *ctx, const unsigned char *in, unsigned char *out, int size, unsigned char iv[32]) {
103 AES_ige_encrypt (in, out, size, &ctx->u.key, iv, AES_DECRYPT);
104}
105
106void tg_ssl_aes_ctr128_crypt (struct tg_aes_ctx *ctx, const unsigned char *in, unsigned char *out, int size, unsigned char iv[16], unsigned char ecount_buf[16], unsigned int *num) {
107 AES_ctr128_encrypt (in, out, size, &ctx->u.key, iv, ecount_buf, num);
108}
109
110static const struct tg_aes_methods ssl_aes_encrypt_methods = {
111 .cbc_crypt = tg_ssl_aes_cbc_encrypt,
112 .ige_crypt = tg_ssl_aes_ige_encrypt,
113 .ctr_crypt = tg_ssl_aes_ctr_crypt,
114 .ctr128_crypt = tg_ssl_aes_ctr128_crypt
115};
116
117void tg_aes_set_encrypt_key (tg_aes_ctx_t *ctx, unsigned char *key, int bits) {
118 AES_set_encrypt_key (key, bits, &ctx->u.key);
119 ctx->type = &ssl_aes_encrypt_methods;
120}
121
122static const struct tg_aes_methods ssl_aes_decrypt_methods = {
123 .cbc_crypt = tg_ssl_aes_cbc_decrypt,
124 .ige_crypt = tg_ssl_aes_ige_decrypt,
125 .ctr_crypt = NULL,
126 .ctr128_crypt = NULL
127};
128
129void tg_aes_set_decrypt_key (tg_aes_ctx_t *ctx, unsigned char *key, int bits) {
130 AES_set_decrypt_key (key, bits, &ctx->u.key);
131 ctx->type = &ssl_aes_decrypt_methods;
132}
133
134void tg_aes_ctx_cleanup (tg_aes_ctx_t *ctx) {
135 memset (ctx, 0, sizeof (tg_aes_ctx_t));
136}
137