/src/ffmpeg/libavutil/aes_ctr.c
Line | Count | Source |
1 | | /* |
2 | | * AES-CTR cipher |
3 | | * Copyright (c) 2015 Eran Kornblau <erankor at gmail dot com> |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include <string.h> |
23 | | |
24 | | #include "aes_ctr.h" |
25 | | #include "aes.h" |
26 | | #include "aes_internal.h" |
27 | | #include "intreadwrite.h" |
28 | | #include "macros.h" |
29 | | #include "mem.h" |
30 | | #include "random_seed.h" |
31 | | |
32 | 0 | #define AES_BLOCK_SIZE (16) |
33 | | |
34 | | typedef struct AVAESCTR { |
35 | | DECLARE_ALIGNED(8, uint8_t, counter)[AES_BLOCK_SIZE]; |
36 | | DECLARE_ALIGNED(8, uint8_t, encrypted_counter)[AES_BLOCK_SIZE]; |
37 | | int block_offset; |
38 | | AVAES aes; |
39 | | } AVAESCTR; |
40 | | |
41 | | struct AVAESCTR *av_aes_ctr_alloc(void) |
42 | 0 | { |
43 | 0 | return av_mallocz(sizeof(struct AVAESCTR)); |
44 | 0 | } |
45 | | |
46 | | void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv) |
47 | 0 | { |
48 | 0 | memcpy(a->counter, iv, AES_CTR_IV_SIZE); |
49 | 0 | memset(a->counter + AES_CTR_IV_SIZE, 0, sizeof(a->counter) - AES_CTR_IV_SIZE); |
50 | 0 | a->block_offset = 0; |
51 | 0 | } |
52 | | |
53 | | void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv) |
54 | 0 | { |
55 | 0 | memcpy(a->counter, iv, sizeof(a->counter)); |
56 | 0 | a->block_offset = 0; |
57 | 0 | } |
58 | | |
59 | | const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a) |
60 | 0 | { |
61 | 0 | return a->counter; |
62 | 0 | } |
63 | | |
64 | | void av_aes_ctr_set_random_iv(struct AVAESCTR *a) |
65 | 0 | { |
66 | 0 | uint32_t iv[2]; |
67 | |
|
68 | 0 | iv[0] = av_get_random_seed(); |
69 | 0 | iv[1] = av_get_random_seed(); |
70 | |
|
71 | 0 | av_aes_ctr_set_iv(a, (uint8_t*)iv); |
72 | 0 | } |
73 | | |
74 | | int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key) |
75 | 0 | { |
76 | 0 | av_aes_init(&a->aes, key, 128, 0); |
77 | |
|
78 | 0 | memset(a->counter, 0, sizeof(a->counter)); |
79 | 0 | a->block_offset = 0; |
80 | |
|
81 | 0 | return 0; |
82 | 0 | } |
83 | | |
84 | | void av_aes_ctr_free(struct AVAESCTR *a) |
85 | 1.14M | { |
86 | 1.14M | av_free(a); |
87 | 1.14M | } |
88 | | |
89 | | static inline void av_aes_ctr_increment_be64(uint8_t* counter) |
90 | 0 | { |
91 | 0 | uint64_t c = AV_RB64A(counter) + 1; |
92 | 0 | AV_WB64A(counter, c); |
93 | 0 | } |
94 | | |
95 | | void av_aes_ctr_increment_iv(struct AVAESCTR *a) |
96 | 0 | { |
97 | 0 | av_aes_ctr_increment_be64(a->counter); |
98 | 0 | memset(a->counter + AES_CTR_IV_SIZE, 0, sizeof(a->counter) - AES_CTR_IV_SIZE); |
99 | 0 | a->block_offset = 0; |
100 | 0 | } |
101 | | |
102 | | void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int count) |
103 | 0 | { |
104 | 0 | if (a->block_offset && count > 0) { |
105 | 0 | int left = FFMIN(count, AES_BLOCK_SIZE - a->block_offset); |
106 | 0 | for (int len = 0; len < left; len++) |
107 | 0 | dst[len] = src[len] ^ a->encrypted_counter[a->block_offset++]; |
108 | 0 | a->block_offset &= AES_BLOCK_SIZE - 1; |
109 | 0 | dst += left; |
110 | 0 | src += left; |
111 | 0 | count -= left; |
112 | 0 | } |
113 | |
|
114 | 0 | while (count >= AES_BLOCK_SIZE) { |
115 | 0 | av_aes_crypt(&a->aes, a->encrypted_counter, a->counter, 1, NULL, 0); |
116 | 0 | av_aes_ctr_increment_be64(a->counter + 8); |
117 | | #if HAVE_FAST_64BIT |
118 | | for (int len = 0; len < AES_BLOCK_SIZE; len += 8) |
119 | | AV_WN64(&dst[len], AV_RN64(&src[len]) ^ AV_RN64A(&a->encrypted_counter[len])); |
120 | | #else |
121 | 0 | for (int len = 0; len < AES_BLOCK_SIZE; len += 4) |
122 | 0 | AV_WN32(&dst[len], AV_RN32(&src[len]) ^ AV_RN32A(&a->encrypted_counter[len])); |
123 | 0 | #endif |
124 | 0 | dst += AES_BLOCK_SIZE; |
125 | 0 | src += AES_BLOCK_SIZE; |
126 | 0 | count -= AES_BLOCK_SIZE; |
127 | 0 | } |
128 | |
|
129 | 0 | if (count > 0) { |
130 | 0 | av_aes_crypt(&a->aes, a->encrypted_counter, a->counter, 1, NULL, 0); |
131 | 0 | av_aes_ctr_increment_be64(a->counter + 8); |
132 | 0 | for (int len = 0; len < count; len++) |
133 | 0 | dst[len] = src[len] ^ a->encrypted_counter[a->block_offset++]; |
134 | 0 | } |
135 | 0 | } |