1305549Sjhb/* crypto/aes/aes_wrap.c */
2305549Sjhb/*
3305549Sjhb * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4305549Sjhb * project.
5305549Sjhb */
6305549Sjhb/* ====================================================================
7305549Sjhb * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8305549Sjhb *
9305549Sjhb * Redistribution and use in source and binary forms, with or without
10305549Sjhb * modification, are permitted provided that the following conditions
11305549Sjhb * are met:
12305549Sjhb *
13305549Sjhb * 1. Redistributions of source code must retain the above copyright
14305549Sjhb *    notice, this list of conditions and the following disclaimer.
15305549Sjhb *
16305549Sjhb * 2. Redistributions in binary form must reproduce the above copyright
17305549Sjhb *    notice, this list of conditions and the following disclaimer in
18305549Sjhb *    the documentation and/or other materials provided with the
19305549Sjhb *    distribution.
20305549Sjhb *
21305549Sjhb * 3. All advertising materials mentioning features or use of this
22305549Sjhb *    software must display the following acknowledgment:
23305549Sjhb *    "This product includes software developed by the OpenSSL Project
24305549Sjhb *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25305549Sjhb *
26305549Sjhb * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27305549Sjhb *    endorse or promote products derived from this software without
28305549Sjhb *    prior written permission. For written permission, please contact
29305549Sjhb *    licensing@OpenSSL.org.
30305549Sjhb *
31305549Sjhb * 5. Products derived from this software may not be called "OpenSSL"
32305549Sjhb *    nor may "OpenSSL" appear in their names without prior written
33305549Sjhb *    permission of the OpenSSL Project.
34305549Sjhb *
35309529Skib * 6. Redistributions of any form whatsoever must retain the following
36305549Sjhb *    acknowledgment:
37305549Sjhb *    "This product includes software developed by the OpenSSL Project
38309447Sjhb *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39305549Sjhb *
40305549Sjhb * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41305549Sjhb * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42305549Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43305549Sjhb * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44305549Sjhb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45305549Sjhb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46305549Sjhb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47305549Sjhb * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48305549Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49305549Sjhb * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50305549Sjhb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51305549Sjhb * OF THE POSSIBILITY OF SUCH DAMAGE.
52305549Sjhb * ====================================================================
53305549Sjhb */
54305549Sjhb
55305549Sjhb#include "cryptlib.h"
56305549Sjhb#include <openssl/aes.h>
57305549Sjhb#include <openssl/bio.h>
58305549Sjhb
59305549Sjhbstatic const unsigned char default_iv[] = {
60305549Sjhb    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
61305549Sjhb};
62305549Sjhb
63305549Sjhbint AES_wrap_key(AES_KEY *key, const unsigned char *iv,
64305549Sjhb                 unsigned char *out,
65305549Sjhb                 const unsigned char *in, unsigned int inlen)
66305549Sjhb{
67305549Sjhb    unsigned char *A, B[16], *R;
68305549Sjhb    unsigned int i, j, t;
69305549Sjhb    if ((inlen & 0x7) || (inlen < 8))
70305549Sjhb        return -1;
71305549Sjhb    A = B;
72305549Sjhb    t = 1;
73305549Sjhb    memcpy(out + 8, in, inlen);
74305549Sjhb    if (!iv)
75305549Sjhb        iv = default_iv;
76305549Sjhb
77305549Sjhb    memcpy(A, iv, 8);
78305549Sjhb
79305549Sjhb    for (j = 0; j < 6; j++) {
80305549Sjhb        R = out + 8;
81305549Sjhb        for (i = 0; i < inlen; i += 8, t++, R += 8) {
82305549Sjhb            memcpy(B + 8, R, 8);
83305549Sjhb            AES_encrypt(B, B, key);
84305549Sjhb            A[7] ^= (unsigned char)(t & 0xff);
85305549Sjhb            if (t > 0xff) {
86305549Sjhb                A[6] ^= (unsigned char)((t >> 8) & 0xff);
87305549Sjhb                A[5] ^= (unsigned char)((t >> 16) & 0xff);
88305549Sjhb                A[4] ^= (unsigned char)((t >> 24) & 0xff);
89305549Sjhb            }
90305549Sjhb            memcpy(R, B + 8, 8);
91305549Sjhb        }
92305549Sjhb    }
93305549Sjhb    memcpy(out, A, 8);
94305549Sjhb    return inlen + 8;
95305549Sjhb}
96305549Sjhb
97305549Sjhbint AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
98305549Sjhb                   unsigned char *out,
99305549Sjhb                   const unsigned char *in, unsigned int inlen)
100305549Sjhb{
101305549Sjhb    unsigned char *A, B[16], *R;
102305549Sjhb    unsigned int i, j, t;
103305549Sjhb    inlen -= 8;
104305549Sjhb    if (inlen & 0x7)
105305549Sjhb        return -1;
106305549Sjhb    if (inlen < 8)
107305549Sjhb        return -1;
108305549Sjhb    A = B;
109305549Sjhb    t = 6 * (inlen >> 3);
110305549Sjhb    memcpy(A, in, 8);
111305549Sjhb    memcpy(out, in + 8, inlen);
112305549Sjhb    for (j = 0; j < 6; j++) {
113305549Sjhb        R = out + inlen - 8;
114305549Sjhb        for (i = 0; i < inlen; i += 8, t--, R -= 8) {
115305549Sjhb            A[7] ^= (unsigned char)(t & 0xff);
116309560Sjhb            if (t > 0xff) {
117318844Snp                A[6] ^= (unsigned char)((t >> 8) & 0xff);
118309560Sjhb                A[5] ^= (unsigned char)((t >> 16) & 0xff);
119309560Sjhb                A[4] ^= (unsigned char)((t >> 24) & 0xff);
120318844Snp            }
121318844Snp            memcpy(B + 8, R, 8);
122318844Snp            AES_decrypt(B, B, key);
123318844Snp            memcpy(R, B + 8, 8);
124309560Sjhb        }
125309560Sjhb    }
126318844Snp    if (!iv)
127309560Sjhb        iv = default_iv;
128318844Snp    if (memcmp(A, iv, 8)) {
129318844Snp        OPENSSL_cleanse(out, inlen);
130318844Snp        return 0;
131318844Snp    }
132318844Snp    return inlen;
133318844Snp}
134318844Snp
135318844Snp#ifdef AES_WRAP_TEST
136305549Sjhb
137305549Sjhbint AES_wrap_unwrap_test(const unsigned char *kek, int keybits,
138305549Sjhb                         const unsigned char *iv,
139305549Sjhb                         const unsigned char *eout,
140305549Sjhb                         const unsigned char *key, int keylen)
141305549Sjhb{
142305549Sjhb    unsigned char *otmp = NULL, *ptmp = NULL;
143305549Sjhb    int r, ret = 0;
144305549Sjhb    AES_KEY wctx;
145305549Sjhb    otmp = OPENSSL_malloc(keylen + 8);
146305549Sjhb    ptmp = OPENSSL_malloc(keylen);
147305549Sjhb    if (!otmp || !ptmp)
148305549Sjhb        return 0;
149309449Sjhb    if (AES_set_encrypt_key(kek, keybits, &wctx))
150305549Sjhb        goto err;
151305549Sjhb    r = AES_wrap_key(&wctx, iv, otmp, key, keylen);
152305549Sjhb    if (r <= 0)
153305549Sjhb        goto err;
154305549Sjhb
155305549Sjhb    if (eout && memcmp(eout, otmp, keylen))
156305549Sjhb        goto err;
157305549Sjhb
158305549Sjhb    if (AES_set_decrypt_key(kek, keybits, &wctx))
159305549Sjhb        goto err;
160305549Sjhb    r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r);
161305549Sjhb
162305549Sjhb    if (memcmp(key, ptmp, keylen))
163305549Sjhb        goto err;
164305549Sjhb
165309449Sjhb    ret = 1;
166305549Sjhb
167305549Sjhb err:
168305549Sjhb    if (otmp)
169305549Sjhb        OPENSSL_free(otmp);
170305549Sjhb    if (ptmp)
171305549Sjhb        OPENSSL_free(ptmp);
172305549Sjhb
173305549Sjhb    return ret;
174305549Sjhb
175305549Sjhb}
176305549Sjhb
177305549Sjhbint main(int argc, char **argv)
178309560Sjhb{
179309560Sjhb
180309560Sjhb    static const unsigned char kek[] = {
181309560Sjhb        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
182309560Sjhb        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
183309560Sjhb        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
184309560Sjhb        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
185309560Sjhb    };
186309560Sjhb
187309560Sjhb    static const unsigned char key[] = {
188309560Sjhb        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
189309560Sjhb        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
190309560Sjhb        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
191309560Sjhb        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
192309560Sjhb    };
193309560Sjhb
194305549Sjhb    static const unsigned char e1[] = {
195305549Sjhb        0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
196305549Sjhb        0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82,
197305549Sjhb        0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5
198305549Sjhb    };
199305549Sjhb
200305549Sjhb    static const unsigned char e2[] = {
201305549Sjhb        0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35,
202305549Sjhb        0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2,
203305549Sjhb        0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d
204305549Sjhb    };
205305549Sjhb
206305549Sjhb    static const unsigned char e3[] = {
207305549Sjhb        0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2,
208305549Sjhb        0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a,
209305549Sjhb        0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7
210305549Sjhb    };
211305549Sjhb
212305549Sjhb    static const unsigned char e4[] = {
213305549Sjhb        0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32,
214305549Sjhb        0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc,
215305549Sjhb        0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93,
216305549Sjhb        0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2
217305549Sjhb    };
218305549Sjhb
219305549Sjhb    static const unsigned char e5[] = {
220305549Sjhb        0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f,
221305549Sjhb        0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4,
222305549Sjhb        0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95,
223305549Sjhb        0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1
224305549Sjhb    };
225305549Sjhb
226305549Sjhb    static const unsigned char e6[] = {
227305549Sjhb        0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4,
228305549Sjhb        0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26,
229305549Sjhb        0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26,
230305549Sjhb        0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b,
231305549Sjhb        0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21
232305549Sjhb    };
233305549Sjhb
234305549Sjhb    AES_KEY wctx, xctx;
235305549Sjhb    int ret;
236305549Sjhb    ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16);
237305549Sjhb    fprintf(stderr, "Key test result %d\n", ret);
238305549Sjhb    ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16);
239305549Sjhb    fprintf(stderr, "Key test result %d\n", ret);
240305549Sjhb    ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16);
241305549Sjhb    fprintf(stderr, "Key test result %d\n", ret);
242305549Sjhb    ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24);
243305549Sjhb    fprintf(stderr, "Key test result %d\n", ret);
244305549Sjhb    ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24);
245305549Sjhb    fprintf(stderr, "Key test result %d\n", ret);
246305549Sjhb    ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32);
247305549Sjhb    fprintf(stderr, "Key test result %d\n", ret);
248305549Sjhb}
249305549Sjhb
250305549Sjhb#endif
251305549Sjhb