aes_wrap.c revision 296465
1/* crypto/aes/aes_wrap.c */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 */
54
55#include "cryptlib.h"
56#include <openssl/aes.h>
57#include <openssl/bio.h>
58
59static const unsigned char default_iv[] = {
60    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
61};
62
63int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
64                 unsigned char *out,
65                 const unsigned char *in, unsigned int inlen)
66{
67    unsigned char *A, B[16], *R;
68    unsigned int i, j, t;
69    if ((inlen & 0x7) || (inlen < 8))
70        return -1;
71    A = B;
72    t = 1;
73    memcpy(out + 8, in, inlen);
74    if (!iv)
75        iv = default_iv;
76
77    memcpy(A, iv, 8);
78
79    for (j = 0; j < 6; j++) {
80        R = out + 8;
81        for (i = 0; i < inlen; i += 8, t++, R += 8) {
82            memcpy(B + 8, R, 8);
83            AES_encrypt(B, B, key);
84            A[7] ^= (unsigned char)(t & 0xff);
85            if (t > 0xff) {
86                A[6] ^= (unsigned char)((t >> 8) & 0xff);
87                A[5] ^= (unsigned char)((t >> 16) & 0xff);
88                A[4] ^= (unsigned char)((t >> 24) & 0xff);
89            }
90            memcpy(R, B + 8, 8);
91        }
92    }
93    memcpy(out, A, 8);
94    return inlen + 8;
95}
96
97int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
98                   unsigned char *out,
99                   const unsigned char *in, unsigned int inlen)
100{
101    unsigned char *A, B[16], *R;
102    unsigned int i, j, t;
103    inlen -= 8;
104    if (inlen & 0x7)
105        return -1;
106    if (inlen < 8)
107        return -1;
108    A = B;
109    t = 6 * (inlen >> 3);
110    memcpy(A, in, 8);
111    memcpy(out, in + 8, inlen);
112    for (j = 0; j < 6; j++) {
113        R = out + inlen - 8;
114        for (i = 0; i < inlen; i += 8, t--, R -= 8) {
115            A[7] ^= (unsigned char)(t & 0xff);
116            if (t > 0xff) {
117                A[6] ^= (unsigned char)((t >> 8) & 0xff);
118                A[5] ^= (unsigned char)((t >> 16) & 0xff);
119                A[4] ^= (unsigned char)((t >> 24) & 0xff);
120            }
121            memcpy(B + 8, R, 8);
122            AES_decrypt(B, B, key);
123            memcpy(R, B + 8, 8);
124        }
125    }
126    if (!iv)
127        iv = default_iv;
128    if (memcmp(A, iv, 8)) {
129        OPENSSL_cleanse(out, inlen);
130        return 0;
131    }
132    return inlen;
133}
134
135#ifdef AES_WRAP_TEST
136
137int AES_wrap_unwrap_test(const unsigned char *kek, int keybits,
138                         const unsigned char *iv,
139                         const unsigned char *eout,
140                         const unsigned char *key, int keylen)
141{
142    unsigned char *otmp = NULL, *ptmp = NULL;
143    int r, ret = 0;
144    AES_KEY wctx;
145    otmp = OPENSSL_malloc(keylen + 8);
146    ptmp = OPENSSL_malloc(keylen);
147    if (!otmp || !ptmp)
148        return 0;
149    if (AES_set_encrypt_key(kek, keybits, &wctx))
150        goto err;
151    r = AES_wrap_key(&wctx, iv, otmp, key, keylen);
152    if (r <= 0)
153        goto err;
154
155    if (eout && memcmp(eout, otmp, keylen))
156        goto err;
157
158    if (AES_set_decrypt_key(kek, keybits, &wctx))
159        goto err;
160    r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r);
161
162    if (memcmp(key, ptmp, keylen))
163        goto err;
164
165    ret = 1;
166
167 err:
168    if (otmp)
169        OPENSSL_free(otmp);
170    if (ptmp)
171        OPENSSL_free(ptmp);
172
173    return ret;
174
175}
176
177int main(int argc, char **argv)
178{
179
180    static const unsigned char kek[] = {
181        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
182        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
183        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
184        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
185    };
186
187    static const unsigned char key[] = {
188        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
189        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
190        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
191        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
192    };
193
194    static const unsigned char e1[] = {
195        0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
196        0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82,
197        0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5
198    };
199
200    static const unsigned char e2[] = {
201        0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35,
202        0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2,
203        0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d
204    };
205
206    static const unsigned char e3[] = {
207        0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2,
208        0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a,
209        0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7
210    };
211
212    static const unsigned char e4[] = {
213        0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32,
214        0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc,
215        0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93,
216        0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2
217    };
218
219    static const unsigned char e5[] = {
220        0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f,
221        0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4,
222        0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95,
223        0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1
224    };
225
226    static const unsigned char e6[] = {
227        0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4,
228        0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26,
229        0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26,
230        0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b,
231        0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21
232    };
233
234    AES_KEY wctx, xctx;
235    int ret;
236    ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16);
237    fprintf(stderr, "Key test result %d\n", ret);
238    ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16);
239    fprintf(stderr, "Key test result %d\n", ret);
240    ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16);
241    fprintf(stderr, "Key test result %d\n", ret);
242    ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24);
243    fprintf(stderr, "Key test result %d\n", ret);
244    ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24);
245    fprintf(stderr, "Key test result %d\n", ret);
246    ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32);
247    fprintf(stderr, "Key test result %d\n", ret);
248}
249
250#endif
251