1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2011-2012 Planets Communications B.V.
5 Copyright (C) 2013-2018 Bareos GmbH & Co. KG
6
7 This program is Free Software; you can redistribute it and/or
8 modify it under the terms of version three of the GNU Affero General Public
9 License as published by the Free Software Foundation and included
10 in the file LICENSE.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22 /*
23 * crypto_wrap.c Encryption key wrapping support functions
24 *
25 * crypto_wrap.c was based on sample code used in multiple
26 * other projects and has the following copyright:
27 *
28 * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
29 *
30 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
31 *
32 * This program is free software; you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License version 2 as
34 * published by the Free Software Foundation.
35 *
36 * Alternatively, this software may be distributed under the terms of BSD
37 * license.
38 *
39 * Adapted to BAREOS by Marco van Wieringen, March 2012
40 */
41
42 #include "include/bareos.h"
43 #include "lib/crypto_wrap.h"
44
45 #if defined(HAVE_OPENSSL)
46
47 # ifdef HAVE_OPENSSL
48 # include <openssl/aes.h>
49 # endif
50
51 /*
52 * @kek: key encryption key (KEK)
53 * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
54 * @plain: plaintext key to be wrapped, n * 64 bit
55 * @cipher: wrapped key, (n + 1) * 64 bit
56 */
AesWrap(uint8_t * kek,int n,uint8_t * plain,uint8_t * cipher)57 void AesWrap(uint8_t* kek, int n, uint8_t* plain, uint8_t* cipher)
58 {
59 uint8_t *a, *r, b[16];
60 int i, j;
61 # ifdef HAVE_OPENSSL
62 AES_KEY key;
63 # endif
64
65 a = cipher;
66 r = cipher + 8;
67
68 /*
69 * 1) Initialize variables.
70 */
71 memset(a, 0xa6, 8);
72 memcpy(r, plain, 8 * n);
73
74 # ifdef HAVE_OPENSSL
75 AES_set_encrypt_key(kek, 128, &key);
76 # endif
77
78 /*
79 * 2) Calculate intermediate values.
80 * For j = 0 to 5
81 * For i=1 to n
82 * B = AES(K, A | R[i])
83 * A = MSB(64, B) ^ t where t = (n*j)+i
84 * R[i] = LSB(64, B)
85 */
86 for (j = 0; j <= 5; j++) {
87 r = cipher + 8;
88 for (i = 1; i <= n; i++) {
89 memcpy(b, a, 8);
90 memcpy(b + 8, r, 8);
91 # ifdef HAVE_OPENSSL
92 AES_encrypt(b, b, &key);
93 # endif
94 memcpy(a, b, 8);
95 a[7] ^= n * j + i;
96 memcpy(r, b + 8, 8);
97 r += 8;
98 }
99 }
100
101 /* 3) Output the results.
102 *
103 * These are already in @cipher due to the location of temporary
104 * variables.
105 */
106 }
107
108 /*
109 * @kek: key encryption key (KEK)
110 * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
111 * @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit
112 * @plain: plaintext key, n * 64 bit
113 */
AesUnwrap(uint8_t * kek,int n,uint8_t * cipher,uint8_t * plain)114 int AesUnwrap(uint8_t* kek, int n, uint8_t* cipher, uint8_t* plain)
115 {
116 uint8_t a[8], *r, b[16];
117 int i, j;
118 # ifdef HAVE_OPENSSL
119 AES_KEY key;
120 # endif
121
122 /*
123 * 1) Initialize variables.
124 */
125 memcpy(a, cipher, 8);
126 r = plain;
127 memcpy(r, cipher + 8, 8 * n);
128
129 # ifdef HAVE_OPENSSL
130 AES_set_decrypt_key(kek, 128, &key);
131 # endif
132
133 /*
134 * 2) Compute intermediate values.
135 * For j = 5 to 0
136 * For i = n to 1
137 * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
138 * A = MSB(64, B)
139 * R[i] = LSB(64, B)
140 */
141 for (j = 5; j >= 0; j--) {
142 r = plain + (n - 1) * 8;
143 for (i = n; i >= 1; i--) {
144 memcpy(b, a, 8);
145 b[7] ^= n * j + i;
146
147 memcpy(b + 8, r, 8);
148 # ifdef HAVE_OPENSSL
149 AES_decrypt(b, b, &key);
150 # endif
151 memcpy(a, b, 8);
152 memcpy(r, b + 8, 8);
153 r -= 8;
154 }
155 }
156
157 /*
158 * 3) Output results.
159 *
160 * These are already in @plain due to the location of temporary
161 * variables. Just verify that the IV matches with the expected value.
162 */
163 for (i = 0; i < 8; i++) {
164 if (a[i] != 0xa6) { return -1; }
165 }
166
167 return 0;
168 }
169 #else
170 /*
171 * @kek: key encryption key (KEK)
172 * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
173 * @plain: plaintext key to be wrapped, n * 64 bit
174 * @cipher: wrapped key, (n + 1) * 64 bit
175 */
AesWrap(uint8_t * kek,int n,uint8_t * plain,uint8_t * cipher)176 void AesWrap(uint8_t* kek, int n, uint8_t* plain, uint8_t* cipher)
177 {
178 memcpy(cipher, plain, n * 8);
179 }
180
181 /*
182 * @kek: key encryption key (KEK)
183 * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
184 * @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit
185 * @plain: plaintext key, n * 64 bit
186 */
AesUnwrap(uint8_t * kek,int n,uint8_t * cipher,uint8_t * plain)187 int AesUnwrap(uint8_t* kek, int n, uint8_t* cipher, uint8_t* plain)
188 {
189 memcpy(cipher, plain, n * 8);
190 return 0;
191 }
192 #endif /* HAVE_OPENSSL */
193